Merge Sorted Array
Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.
和pascall triangle相似的思路,不过这次空间已经开好了。后方空间是空闲的,所以从后向前进行处理,可以避免先处理前面导致需要空间交换。
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1, j = n - 1;
int k = m + n - 1;
while (i > -1 && j > -1){
if (nums1[i] > nums2[j]) nums1[k--] = nums1[i--];
else nums1[k--] = nums2[j--];
}
while (i > -1) nums1[k--] = nums1[i--];
while (j > -1) nums1[k--] = nums2[j--];
}
Search in Rotated Sorted Array
解法1:基本思想是二分查找,首先利用二分查找找到最小值的位置,然后将数组看做是平移之后的,
数组整体向右移了minIndex个单位,数组[(i+minIndex)%n]是非rotated且有序的,left,right可以看做是index
关于left/right是half+-1还是half,用相邻的数模拟临界值试一下就好了。
int search(vector<int>& nums, int target) {
int left = 0;
int right=nums.size() - 1;
int half = 0;
int minIndex = 0;
while (left < right){ //能找到左边界,所以left可以half+1
half =(left + right) / 2;
if (nums[half] > nums[right])
left = half+1;
else
right = half;
}
minIndex = left;
left = 0;
right = nums.size() - 1;
int realHalf = 0;
while (left <= right){
half = (left + right)/2;
realHalf = (half + minIndex) % nums.size(); //
if(nums[realHalf] == target) return realHalf;
if(nums[realHalf] > target)
right = half - 1;
else
left = half + 1;
}
return -1;
}
解法2:
对于rotated array来说,比如[4,5,6,7,1,2,3],一定有一部分是有序的,如果target在有序的那一部分,那么可以在那一部分进行二分查找;如果不在,则丢到另一部分中寻找,最后一定可以找到target处于某有序的部分。
int search(vector<int>& nums, int target) {
int lo = 0, hi = nums.size() - 1;
int mid = 0;
while (lo < hi){
mid = (lo + hi) / 2;
if (nums[mid] == target) return mid;
if (nums[mid] > nums[hi]){
if (nums[mid] > target && nums[lo] <= target) hi = mid; //target在有序的部分
else lo = mid + 1;
}else if (nums[mid] < nums[hi]){
if (nums[mid] < target && nums[hi] >= target) lo = mid + 1; //target在有序的部分
else hi = mid;
}
}
return nums[lo] == target ? lo : -1;
}
Search in Rotated Sorted Array II
Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
这个和上一道题的区别在于当两个数相同时,比如 nums[mid] = nums[hi]时,不能说明mid和hi指针相同,需要移动直到两者不等。
此时如果采用解法1的变体,需要改写两段二分查找,虽然可行,但是代码量稍多
int lo = 0, hi = nums.size() - 1;
int mid = 0;
while (lo < hi){
mid = (lo+hi)/2;
if (nums[mid] == target) return true;
if (nums[mid] > nums[hi]){
if (nums[mid] > target && nums[lo] <= target) hi = mid;
else lo = mid + 1;
}else if (nums[mid] < nums[hi]){
if (nums[mid] < target && nums[hi] >= target) lo = mid + 1;
else hi = mid;
}else
hi--;
}
return nums[lo] == target ? true : false;
Triangle
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
[ [2], [3,4], [6,5,7], [4,1,8,3] ]
The minimum path sum from top to bottom is 11
(i.e., 2 + 3 + 5 + 1 = 11).
感觉思想也属于dp。用一个vector存储每一行,包含该行每个数的最短路径是多少,vector进行循环使用,因为只有上一行的状态是有用的,最后一行统计vector中最小的。
空间复杂度O(n)
int minimumTotal(vector<vector<int>>& triangle) {
int n = triangle.size();
vector<int> dp(n, 0);
dp[0] = triangle[0][0];
for (int k = 1; k < n; k++){
dp[k] = dp[k-1] + triangle[k][k];
for (int i = k - 1; i > 0; i--){ //一定是从后往前,不然会有影响
dp[i] = triangle[k][i] + min(dp[i], dp[i-1]);
}
dp[0] += triangle[k][0];
}
int rst = INT_MAX;
for (int minT : dp)
rst = min(rst, minT);
return rst;
}
Subsets II
Given a collection of integers that might contain duplicates, nums, return all possible subsets.
Note: The solution set must not contain duplicate subsets.
对于没有重复数字的子集,有2^n个,即每个数字出现或不出现;对于重复出现的数字,看做一个特殊数字,特殊数字出现1次、2次或n次。
vector<vector<int> > subsetsWithDup(vector<int> &S) {
vector<vector<int> > totalset = {{}};
sort(S.begin(),S.end());
for(int i=0; i<S.size();){
int count = 0; // num of elements are the same
while(count + i<S.size() && S[count+i]==S[i]) count++;
int previousN = totalset.size();
for(int k=0; k<previousN; k++){
vector<int> instance = totalset[k];
for(int j=0; j<count; j++){
instance.push_back(S[i]);
totalset.push_back(instance);
}
}
i += count;
}
return totalset;
}