- 旋转数组 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例1 输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
示例2 输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]
说明:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的 原地 算法。
方法一
public void rotate(int[] nums, int k) {
int j = 0;
while (j < k) {
int last = nums[nums.length - 1];
for (int i = nums.length - 1; i > 0; i--) {
nums[i] = nums[i - 1];
}
nums[0] = last;
j++;
}
}
方法二:
public void rotate(int[] nums, int k) {
for (int j = 0; j < k; j++) {
int last = nums[nums.length - 1];
for (int i = nums.length - 1; i > 0; i--) {
nums[i] = nums[i - 1];
}
nums[0] = last;
}
}
方法三
public void rotate(int[] nums, int k) {
int temp, previous;
for (int j = 0; j < k; j++) {
previous = nums[nums.length - 1];
for (int i = 0; i < nums.length; i ++) {
temp = nums[i];
nums[i] = previous;
previous = temp;
}
}
}
寻找旋转排序数组中的最小值
方法一:暴力, 时间复杂度为O(n)
public int findMin(int[] nums) {
int min = nums[nums.length - 1], temp, pre = nums[nums.length - 1];
for (int i = 0; i < nums.length; i++) {
min = min < pre ? min : pre;
temp = nums[i];
nums[i] = pre;
pre = temp;
}
return min;
}
方法一:二分搜索 O(logN)
/*
2 3 4 5 6 7
4 5 6 7 2 3 变化点:所有变化点的左侧元素都大于数组第一个元素,变化点右侧元素都小于数组第一个元素
7 2 3 4 5 6
找数组中间元素mid
如果中间元素 > 数组第一个元素, 我们需要在 mid 右边搜索变化点。
如果中间元素 < 数组第一个元素,我们需要在 mid 左边搜索变化点
当我们找到变化点时停止搜索,当以下条件满足任意一个即可:
nums[mid] > nums[mid + 1],因此 mid+1 是最小值。
nums[mid - 1] > nums[mid],因此 mid 是最小值。
*/
public int findMin(int[] nums) {
if (nums.length == 1) return nums[0];
int left = 0, right = nums.length - 1;
if (nums[right] > nums[0]) return nums[0];
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[mid + 1]) return nums[mid + 1];
if (nums[mid - 1] > nums[mid]) return nums[mid];
if (nums[mid] > nums[0]) {
left = mid + 1;
}
if (nums[mid] < nums[0]) {
right = mid - 1;
}
}
return -1;
}