1.旋转数组的最小数字:二分查找
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
class Solution {
public:
int minArray(vector<int>& numbers) {
//二分查找,最小值一定是这两个子数组的分界线
int low=0; //指向左边子数组
int high=numbers.size()-1; //指向右边子数组
int mid=0;
while(low<high){
mid=(low+high)/2; //指向中间
//与numbers[high]进行比较
if(numbers[mid]>numbers[high]) //mid在左子数组中
low=mid+1;
else if(numbers[mid]<numbers[high]) //mid在右子数组中
high=mid;
else //如果相等无法判断在那边,可以缩小范围/或者进行顺序查找
--high;
}
return numbers[low];
}
};
2.合并两个有序数组:逆向双指针
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
//逆向双指针
int p1=m-1; //指向nums1末尾
int p2=n-1; //指向nums2末尾
int max=m+n-1; //将合并的值存放到nums1
while(p1>=0 && p2>=0){
if(nums1[p1]>nums2[p2])
nums1[max--]=nums1[p1--];
else
nums1[max--]=nums2[p2--];
}
while(p2>=0)
nums1[max--]=nums2[p2--];
}
};
3.移除元素:(3~4)
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//双指针
int dst=0,src=0; //指向数组首元素
while(src<nums.size()){ //遍历
if(nums[src]!=val) //如果不是要删除元素
nums[dst++]=nums[src];
++src; //否则跳过
}
return dst;
}
};
4.删除有序数组中的重复项:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==0)
return 0;
//双指针
int dst=0,src=1; //起始时,dst指向数组首元素,src指向数组第二个元素
while(src<nums.size()){
if(nums[src]!=nums[dst])
nums[++dst]=nums[src];
++src;
}
return dst+1;
}
};
5.旋转数组:
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
//使用额外数组
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n=nums.size();
vector<int> v(n);
for(int i=0;i<n;++i){
v[(i+k)%n]=nums[i];
}
nums.assign(v.begin(),v.end());
}
};
//原地旋转
class Solution {
public:
void rotate(vector<int>& nums, int k) {
k = k % nums.size();
reverse(nums.begin(), nums.end()); //翻转所有元素
reverse(nums.begin(), nums.begin() + k); //翻转 [0, k\bmod n - 1][0,kmodn−1] 区间的元素
reverse(nums.begin() + k, nums.end()); //翻转 [k\bmod n, n - 1][kmodn,n−1] 区间的元素
}
};