码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode记录(1)——Array

时间:2016-04-09 20:37:50      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:

1.Two Sum

naive

4.Median of Two Sorted Arrays

找两个已排序数组的中位数

直接数可以过,但很蠢,O(m+n)时间

技术分享
 1 class Solution {
 2 public:
 3     double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
 4         int p1=-1,p2=-1;
 5         double rst = 0;
 6         int len1 = nums1.size(),len2 = nums2.size();
 7         if (len1==0&&len2==0) return 0.0;
 8         
 9         if ((len1+len2)%2==1)
10         {
11             int count=(len1+len2+1)/2;
12             if (len1==0) return 1.0*nums2[len2/2];
13             if (len2==0) return 1.0*nums1[len1/2];
14             while (count)
15             {
16                 if (p1==len1-1) {rst=nums2[p2+1];p2++;}
17                 else if (p2==len2-1) {rst=nums1[p1+1];p1++;}
18                 else if (nums1[p1+1]>nums2[p2+1]) {rst=nums2[p2+1];p2++;}
19                 else {rst=nums1[p1+1];p1++;}
20                 count--;
21             }
22             return rst;
23         }
24         else {
25             int count=(len1+len2)/2;
26             if (len1==0) return 0.5*nums2[len2/2]+0.5*nums2[len2/2-1];
27             if (len2==0) return 0.5*nums1[len1/2]+0.5*nums1[len1/2-1];
28             int t1=0,t2=0;
29             while (count+1)
30             {
31                 t1=t2;
32                 if (p1==len1-1) {p2++;t2=nums2[p2];}
33                 else if (p2==len2-1) {p1++;t2=nums1[p1];}
34                 else if (nums1[p1+1]>nums2[p2+1]) {p2++;t2=nums2[p2];}
35                 else {p1++;t2=nums1[p1];}
36                 count--;
37             }
38             return 0.5*t1+0.5*t2;
39         }
40     }
41 };
Stupid

直接思路是二分,O(log (m+n))

技术分享
 1 class Solution {
 2 public:
 3     double findMedianSortedArrays(vector<int>& num1, vector<int>& num2) {
 4         int size = num1.size() + num2.size();
 5         if (size % 2 == 1) return 1.0*search(num1, num2, 0, 0, size / 2 + 1);
 6         else return 0.5*search(num1, num2, 0, 0, size / 2) + 0.5*search(num1, num2, 0, 0, size / 2 + 1);
 7     }
 8 private:
 9     int _min(int a, int b)
10     {
11         return a>b ? b : a;
12     }
13     int search(vector<int>& nums1, vector<int>& nums2, int s1, int s2, int pos)
14     {
15         //TODO:nums1[s1,s1+1,...,m],nums2[s2,s2+1,...,n],find the "pos"th smallest number
16         if ((nums1.size() - s1)>(nums2.size() - s2)) 
17             return search(nums2, nums1, s2, s1, pos);      //use 1 extra call to ensure that nums1 is shorter
18         
19         if (s1 == nums1.size()) 
20             return nums2[s2 + pos-1];
21         if (pos == 1) return _min(nums1[s1], nums2[s2]);    //Point 1:边界特殊处理,否则RE
22 
23         int k1 = _min(nums1.size() - s1, pos / 2);
24         int k2 = pos - k1;
25 
26         if (nums1[s1 + k1 - 1] == nums2[s2 + k2 - 1])        //Point 2:等于的情况就不应该步进了
27             return nums1[s1 + k1 - 1];
28         else if (nums1[s1 + k1 - 1] > nums2[s2 + k2 - 1]) 
29             return search(nums1, nums2, s1, s2 + k2, pos - k2);
30         else 
31             return search(nums1, nums2, s1 + k1, s2, pos - k1);
32     }
33 };
Binary Search

11.Container With Most Water

找h[i],h[j],使得min(h[i],h[j])*(j-i)最大

典型的双指针问题,从两端向中间逼近,注意移动条件

技术分享
 1 class Solution {
 2 public:
 3     int maxArea(vector<int>& height) {
 4         int left = 0,right = height.size()-1;
 5         int rst = 0;
 6         while (left<right)
 7         {
 8             rst = _max(rst,(right-left)*_min(height[left],height[right]));
 9             if (height[left]>height[right]) right--;        //当h[l]>h[r]时,显然挪动左侧获得的结果不可能比此刻更好,因而挪右侧
10             else left++;                                    //同理
11         }
12         return rst;
13     }
14 private:
15     int _min(int a,int b)
16     {
17         return a>b?b:a;
18     }
19     int _max(int a,int b)
20     {
21         return a>b?a:b;
22     }
23 };
View Code

15.3Sum

思路:先排序,之后对每一个小于0的数进行查询:

设num[i]<0,则b=i+1,c=num.size()-1,根据和的正/负/0向中间逼近

注意:1.去重  2.数组越界  3.终止条件(当num[i]>0时,由于已排序,后面不必再扫)

技术分享
 1 class Solution {
 2 public:
 3     vector<vector<int>> threeSum(vector<int>& nums) {
 4         vector<vector<int>> rst;
 5         if (nums.size()<3) return rst;
 6         sort(nums.begin(), nums.end());
 7         int i = 0, a = nums[i];
 8         while (i<=nums.size()-3)
 9         {
10             int b = i + 1, c = nums.size() - 1;
11             while (b<c) {
12                 int l = nums[b], r = nums[c];
13                 if (nums[i] + nums[b] + nums[c] == 0)
14                 {
15                     vector<int> t({ nums[i],nums[b],nums[c] });
16                     rst.push_back(t);
17                     while ((b<nums.size())&&(nums[b] == l)) b++;
18                     while ((c>=0)&&(nums[c] == r)) c--;
19                 }
20                 else if (nums[i] + nums[b] + nums[c]<0) { while ((b<nums.size()) && (nums[b] == l)) b++; }
21                 else { while ((c>=0) && (nums[c] == r)) c--; }
22             }
23             while ((i<=nums.size()-3)&&(nums[i] == a)) i++;
24             a = nums[i];
25         }
26         return rst;
27     }
28 };
View Code

16.3Sum Closest

思路:不需要去重,直接双指针找即可,比15简单

技术分享
 1 class Solution {
 2 public:
 3     int threeSumClosest(vector<int>& nums, int target) {
 4         if (nums.size()<3) return -1;           //undefined
 5         sort(nums.begin(), nums.end());
 6         int rst = 0x3f3f3f3f;
 7         int a = 0, b, c;
 8         while (a <= nums.size() - 3) {
 9             b = a + 1, c = nums.size() - 1;
10             int l = nums[b], r = nums[c], t = nums[a];
11             while (b<c)
12             {
13                 int temp = nums[a] + l + r;
14                 if (abs(temp - target)<abs(rst - target))
15                     rst = temp;
16                 if (temp>target) { c--; }
17                 else { b++; }
18                 l = nums[b];
19                 r = nums[c];
20             }
21             if (rst == target) break;
22             a++;
23         }
24         return rst;
25     }
26 };
View Code

 18.4Sum

思路:naive:对每个元素搞一次3Sum

优化思路:剪枝:当有两个点已确定时,在循环开始之前先判断最小的两个数加起来是否已经超过要求;最大的两个数加起来是否仍不足

技术分享
 1 class Solution {
 2 public:
 3     vector<vector<int>> fourSum(vector<int>& nums, int target) {
 4         vector<vector<int>> rst;
 5         if (nums.size()<4) return rst;
 6         sort(nums.begin(), nums.end());
 7         int s = 0, start = nums[s];
 8         while (s <= nums.size() - 4)
 9         {
10             int tar = target - start;
11             int i = s + 1, a = nums[i];
12             while (i <= nums.size() - 3)
13             {
14                 int b = i + 1, c = nums.size() - 1;
15                 while (b<c) {
16                     int l = nums[b], r = nums[c];
17                     if (nums[i] + nums[b] + nums[c] == tar)
18                     {
19                         vector<int> t({ nums[s],nums[i],nums[b],nums[c] });
20                         rst.push_back(t);
21                         while ((b<nums.size()) && (nums[b] == l)) b++;
22                         while ((c >= 0) && (nums[c] == r)) c--;
23                     }
24                     else if (nums[i] + nums[b] + nums[c]<tar) {
25                         while ((b<nums.size()) && (nums[b] == l)) b++;
26                     }
27                     else { while ((c >= 0) && (nums[c] == r)) c--; }
28                 }
29                 while ((i <= nums.size() - 3) && (nums[i] == a)) i++;
30                 a = nums[i];
31             }
32             while ((s <= nums.size() - 4) && (nums[s] == start)) s++;
33             start = nums[s];
34         }
35         return rst;
36     }
37 };
Naive
技术分享
 1 class Solution {
 2 public:
 3     vector<vector<int>> fourSum(vector<int>& nums, int target) {
 4         vector<vector<int>> rst;
 5         if (nums.size()<4) return rst;
 6         sort(nums.begin(), nums.end());
 7         for (int i = 0; i < nums.size() - 3; i++)
 8         {
 9             if ((i > 0) && (nums[i] == nums[i - 1])) continue;
10             int t1 = target - nums[i];
11             for (int j = i + 1; j < nums.size() - 2; j++)
12             {
13                 if ((j > i + 1) && (nums[j] == nums[j - 1])) continue;
14                 int t2 = t1 - nums[j];
15                 int k = j + 1, r = nums.size() - 1;
16                 if (nums[k] + nums[k + 1]>t2) break;
17                 if (nums[r - 1] + nums[r] < t2) continue;
18                 while (k < r)
19                 {
20                     if (nums[k] + nums[r] == t2)
21                     {
22                         rst.push_back({ nums[i],nums[j],nums[k],nums[r] });
23                         k++; r--;
24                         while ((k<r) && (nums[k] == nums[k - 1]))k++;
25                         while ((k<r) && (nums[r] == nums[r + 1]))r--;
26                     }
27                     else if (nums[k] + nums[r] < t2)
28                     {
29                         k++;
30                     }
31                     else
32                         r--;
33                 }
34             }
35         }
36         return rst;
37     }
38 };
加优化

 26.Remove Duplicates from Sorted Array

去重,简单题,注意返回值是数组长度

技术分享
 1 class Solution {
 2 public:
 3     int removeDuplicates(vector<int>& nums) {
 4         if (nums.size()==0) return 0;
 5         int p=0;
 6         for (int i=1;i<nums.size();i++)
 7         {
 8             if (nums[i]!=nums[i-1]) nums[++p]=nums[i];
 9         }
10         return p+1;
11     }
12 };
View Code

31.Next Permutation

基础题

算法:初始化:i=0,ii=0,j=0

1.从后向前扫,找到第一对相邻的nums[i]<nums[ii],ii=i+1;

2.从后向前扫,找到第一个大于nums[i]的nums[j]

3.交换nums[i],num[j],并将ii及之后的数组反转

技术分享
1 从后向前扫,显然递减序列是最“大”的排列,因此找到非递减序列的开始
2 第一步后:nums[ii-end]为递减序列,此时将i与nums[ii-end]中的任意一个数交换,都可以保证其为此序列之后的序列(但不一定就是下一个)
3 为了保证是下一个,找到最小的大于i的数,交换
4 注意到交换后ii后面仍为有序序列,为了使得交换后该子序列最“小”,反转该序列即可
证明
技术分享
 1 class Solution {
 2 public:
 3     void nextPermutation(vector<int>& nums) {
 4         int i=0,ii=0,j=0;
 5         for (int k=nums.size()-1;k>0;k--)
 6         {
 7             if (nums[k-1]<nums[k]) {
 8                 i=k-1;ii=k;break;
 9             }
10         }
11         for (int k=nums.size()-1;k>0;k--)
12         {
13             if (nums[k]>nums[i]) {j=k;break;}
14         }
15         swap(nums,i,j);
16         reverse(nums,ii,nums.size()-1);
17     }
18 private:
19     void swap(vector<int>& nums,int a,int b)
20     {
21         int t=nums[a];
22         nums[a]=nums[b];
23         nums[b]=t;
24     }
25     void reverse(vector<int>& nums,int start,int end)
26     {
27         int p=start,q=end;
28         while (p<q)
29         {
30             swap(nums,p,q);
31             p++;q--;
32         }
33     }
34 };
View Code

 

扩展:

1.已知有序数组{a_1,a_2,...,a_n},求第k个排列

第一位后面有(n-1)!种排列,因而第一位的数字应为a[k/(n-1)!],剩余k%(n-1)!种情况

依次确认之后每一位的排列即可

举例说明:如7个数的集合为{1, 2, 3, 4, 5, 6, 7},要求出第n=1654个排列。

(1654 / 6!)取整得2,确定第1位为3,剩下的6个数{1, 2, 4, 5, 6, 7},求第1654 % 6!=214个序列;

(214 / 5!)取整得1,确定第2位为2,剩下5个数{1, 4, 5, 6, 7},求第214 % 5!=94个序列;

(94 / 4!)取整得3,确定第3位为6,剩下4个数{1, 4, 5, 7},求第94 % 4!=22个序列;

(22 / 3!)取整得3,确定第4位为7,剩下3个数{1, 4, 5},求第22 % 3!=4个序列;

(4 / 2!)得2,确定第5为5,剩下2个数{1, 4};由于4 % 2!=0,故第6位和第7位为增序<1 4>;

因此所有排列为:3267514。

(60.Permutation Sequence

技术分享
class Solution {
public:
    string getPermutation(int n, int k) {
        vector<int> vec;
        for (int i=0;i<n;i++)
            vec.push_back(i);
        string str;
        int rank = k-1;
        for (int i=0;i<n;i++)
        {
            int cas = fact(n-i-1);
            int temp = rank/cas;
            rank = rank%cas;
            str+=(1+vec[temp]);
            vec.erase(vec.begin()+temp);
        }
        return str;
    }
private:
    int fact(int n)
    {
        int rst=1;
        while (n>0) {rst*=n;n--;}
        return rst;
    }
};
View Code

注意:数组从0开始还是从1开始)

2.已知一个排列{a_1,a_2,...,a_n},求这是第几个排列

反过来求即可:

第一位序数为k_1,则排列至少为第(k_1-1)*(n-1)!个

依此类推即可

例如3267514:

后6位的全排列为6!,3为{1, 2, 3 ,4 , 5, 6, 7}中第2个元素(从0开始计数),故2*720=1440;

后5位的全排列为5!,2为{1, 2, 4, 5, 6, 7}中第1个元素,故1*5!=120;

后4位的全排列为4!,6为{1, 4, 5, 6, 7}中第3个元素,故3*4!=72;

后3位的全排列为3!,7为{1, 4, 5, 7}中第3个元素,故3*3!=18;

后2位的全排列为2!,5为{1, 4, 5}中第2个元素,故2*2!=4;

最后2位为增序,因此计数0,求和得:1440+120+72+18+4=1654

 参考:http://www.cnblogs.com/devymex/archive/2010/08/17/1801122.html

 (46. Permutations

输出给定无重复数组的全排列

不要脸的做法:next_permutation,效率高于一般的递归,但仍较低(理论上技术分享(n*n!))

一般的做法:递归:理论上为O(n!),实际上优化的好坏与结果关系很大)

技术分享
 1 class Solution {
 2 public:
 3     vector<vector<int>> permute(vector<int>& nums) {
 4         vector<vector<int>> rst;
 5         if (nums.size() == 0) return rst;
 6         allPermute(nums, 0, nums.size() - 1, rst);
 7         return rst;
 8     }
 9 private:
10     vector<vector<int>> allPermute(vector<int>& nums, int k, int len, vector<vector<int>> &rst)
11     {
12         if (k == len) {
13             vector<int> vec;
14             for (int i = 0; i < nums.size(); i++)
15                 vec.push_back(nums[i]);
16             rst.push_back(vec);
17         }
18         else {
19             for (int i = k; i <= len; i++)
20             {
21                 int temp = nums[k];
22                 nums[k] = nums[i];
23                 nums[i] = temp;
24                 allPermute(nums, k + 1, len, rst);
25                 int temp1 = nums[k];
26                 nums[k] = nums[i];
27                 nums[i] = temp1;
28             }
29         }
30         return rst;
31     }
32 };
View Code
技术分享
 1 class Solution {
 2 public:
 3     vector<vector<int>> permute(vector<int>& nums) {
 4         vector<vector<int>> rst;
 5         allPermute(nums, 0, rst);
 6         return rst;
 7     }
 8 private:
 9     void allPermute(vector<int>& nums, int start, vector<vector<int>>& rst)
10     {
11         if (start >= nums.size()-1) rst.push_back(nums);
12         else {
13             for (int i = start; i <= nums.size() - 1; i++)
14             {
15                 swap(nums[i], nums[start]);
16                 allPermute(nums, start + 1, rst);
17                 swap(nums[i], nums[start]);
18             }
19         }
20     }
21 };
72.27%

 33. Search in Rotated Sorted Array

思路:首先找到转折点,之后在两边分别二分搜索,总的复杂度仍为O(logn)

技术分享
 1 class Solution {
 2 public:
 3     int search(vector<int>& nums, int target) {
 4         int pivot = searchPivot(nums,0,nums.size()-1);
 5         int rst = Search(nums,target,0,pivot);
 6         if (rst == -1) rst = Search(nums,target,pivot+1,nums.size()-1);
 7         return rst;
 8     }
 9 private:
10     int searchPivot(vector<int>& nums,int start,int end)
11     {
12         int p = start+(end-start)/2;
13         if (p==start) return p;
14         if (nums[p]>nums[start]) return searchPivot(nums,p,end);
15         else return searchPivot(nums,start,p);
16     }
17     int Search(vector<int>& nums,int target,int start,int end)
18     {
19         if (target>nums[end]||target<nums[start]||start>end) return -1;
20         else {
21             int pivot = start+(end-start)/2;
22             if (nums[pivot]==target) return pivot;
23             else if (nums[pivot]>target) return Search(nums,target,start,pivot-1);
24             else if (nums[pivot]<target) return Search(nums,target,pivot+1,end);
25         }
26     }
27 };
View Code

34. Search for a Range

简单题,二分找到点后扩一下即可

技术分享
 1 class Solution {
 2 public:
 3     vector<int> searchRange(vector<int>& nums, int target) {
 4         int i = Search(nums,target,0,nums.size()-1);
 5         vector<int> rst;
 6         if (i==-1)
 7         {
 8             rst.push_back(-1);
 9             rst.push_back(-1);
10         }
11         else {
12             int s=i,e=i;
13             while (s>0 && nums[s-1]==nums[s]) s--;
14             while (e<nums.size()-1 && nums[e+1]==nums[s]) e++;
15             rst.push_back(s);
16             rst.push_back(e);
17         }
18         return rst;
19     }
20 private:
21     int Search(vector<int>& nums,int target,int start,int end)
22     {
23         if (start>end) return -1;
24         else {
25             int pivot = start+(end-start)/2;
26             if (nums[pivot]==target) return pivot;
27             else if (nums[pivot]>target) return Search(nums,target,start,pivot-1);
28             else if (nums[pivot]<target) return Search(nums,target,pivot+1,end);
29         }
30     }
31 
32 };
View Code

35. Search Insert Position

简单题,此处在找不到该值时,返回start而非-1即可,之后对start进行处理,找到需要的位置

技术分享
 1 class Solution {
 2 public:
 3     int searchInsert(vector<int>& nums, int target) {
 4         int rst = Search(nums,target,0,nums.size()-1);
 5         if (nums[rst]>target)
 6         {
 7             while (rst>0 && nums[rst-1]>target) rst--;
 8         }
 9         else if (nums[rst]<target)
10         {
11             while (rst<nums.size()-1 && nums[rst+1]<target) rst++;
12         }
13         return rst;
14     }
15 private:
16     int Search(vector<int>& nums,int target,int start,int end)
17     {
18         if (start>end) return start;
19         else {
20             int pivot = start+(end-start)/2;
21             if (nums[pivot]==target) return pivot;
22             else if (nums[pivot]>target) return Search(nums,target,start,pivot-1);
23             else if (nums[pivot]<target) return Search(nums,target,pivot+1,end);
24         }
25     }
26 };
View Code

39. Combination Sum

简单回溯题,注意去重时的操作

技术分享
 1 class Solution {
 2 public:
 3     vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
 4         sort(candidates.begin(), candidates.end());
 5         vector<vector<int>> rst;
 6         vector<int> cas;
 7         Find(cas, candidates, target, rst);
 8         return rst;
 9     }
10 private:
11     void Find(vector<int>& sol, vector<int>& candidates, int target, vector<vector<int>>& rst)
12     {
13         if (target == 0) { rst.push_back(sol); return; }
14         for (int i = 0; i < candidates.size(); i++)
15         {
16             if (sol.size()>0 && (sol.back()) > candidates[i]) continue;         //此处要谨慎,不能和下面的if合并,否则遇到一个不符合条件的就直接break
17             if (target >= candidates[i])
18             {
19                 sol.push_back(candidates[i]);
20                 Find(sol, candidates, target - candidates[i], rst);
21                 sol.pop_back();
22             }
23             else break;
24         }
25         return;
26     }
27 };
View Code

40. Combination Sum II

在39的基础上,给定的数字有重复,但每个数字只能用一次

思路:在39的基础上加一个数组记录某个特定数字最多可用几次,额外开销为O(n)

技术分享
 1 class Solution {
 2 public:
 3     vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
 4         vector<vector<int>> rst;
 5         if (candidates.size()==0) return rst;
 6         sort(candidates.begin(), candidates.end());
 7         vector<int> flag,candi;
 8         candi.push_back(candidates[0]);
 9         flag.push_back(1);
10         int p = 0;
11         for (int i=1;i<candidates.size();i++)
12         {
13             if (candidates[i-1]<candidates[i])        //注意去重条件
14             {
15                 candi.push_back(candidates[i]);
16                 flag.push_back(1);
17                 p++;
18             }
19             else {
20                 flag[p]++;
21             }
22         }
23         vector<int> cas;
24         Find(cas, candi, target, rst,flag);
25         return rst;
26     }
27 private:
28     void Find(vector<int>& sol, vector<int>& candidates, int target, vector<vector<int>>& rst,vector<int>& flag)
29     {
30         if (target == 0) { rst.push_back(sol); return; }
31         for (int i = 0; i < candidates.size(); i++)
32         {
33             if (!flag[i]) continue;
34             if ((sol.size()>0) && (sol.back() > candidates[i])) continue;         //此处要谨慎,不能和下面的if合并,否则遇到一个不符合条件的就直接break
35             if (target >= candidates[i])
36             {
37                 flag[i]--;
38                 sol.push_back(candidates[i]);
39                 Find(sol, candidates, target - candidates[i], rst,flag);
40                 sol.pop_back();
41                 flag[i]++;
42             }
43             else break;
44         }
45         return;
46     }
47 };
View Code

 

LeetCode记录(1)——Array

标签:

原文地址:http://www.cnblogs.com/giddens/p/5369591.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!