当前位置:   article > 正文

leetcode笔记|面试经典150_力扣面试经典150题

力扣面试经典150题

数组、字符串

一、合并有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

即要把nums2复制到nums1,要考虑复制速度。

最直接做法是将nums2接到后面然后快排O(nlogn);

P.S.insert不能用,因为nums1的长度已经是m+n;

O(n+m) 做法:

法1:慢一点,要交换,冒泡步骤相当于插入,后面还要复制,回溯

  1. void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
  2. int i=m-1,j=n-1;
  3. while(i>=0&&j>=0){
  4. while(j>=0&&nums1[i]<=nums2[j]){j--;}
  5. if(j>=0)swap(nums1[i],nums2[j]);
  6. int k=i;
  7. while(k>0&&nums1[k-1]>nums1[k]){swap(nums1[k],nums1[k-1]);k--;}
  8. }
  9. for(int k=0;k<n;k++)nums1[k+m]=nums2[k];
  10. }

 法2:一遍扫描,不用回溯,且直接覆盖(最长时间k决定,m+n):

  1. void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
  2. int k=m+n-1;
  3. m--;
  4. n--;
  5. while(n>=0){
  6. while(n>=0&&(m<0||nums2[n]>=nums1[m]))nums1[k--]=nums2[n--];
  7. if(n<0)break;
  8. while(m>=0&&nums1[m]>=nums2[n])nums1[k--]=nums1[m--];
  9. }
  10. }

二、移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

  1. int removeElement(vector<int>& nums, int val) {
  2. int j=nums.size()-1;
  3. while(j>=0){
  4. while(j>=0&&nums[j]==val)j--;
  5. int i=j;
  6. while(i>=0&&nums[i]!=val)i--;
  7. if(i<0)break;
  8. swap(nums[i],nums[j]);
  9. }
  10. return j+1;
  11. }

三、删除数组重复项

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

  1. class Solution {
  2. public:
  3. int removeDuplicates(vector<int>& nums) {
  4. int i=nums.size()-1;
  5. int len=nums.size();
  6. int j=i;
  7. while(i>0){
  8. while(j>0&&nums[j]!=nums[j-1])j--;
  9. int k=j-1;
  10. while(k>=0&&nums[k]==nums[j])k--;
  11. k++;
  12. len-=(j-k);
  13. int q=k;
  14. while(j>0&&j<i)swap(nums[++q],nums[++j]);
  15. i=q;
  16. j=k;
  17. }
  18. return len;
  19. }
  20. };

四、找多数元素--投票法

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

维护目标数变量result(int),和出现次数count

遍历若当前值等于result(投给了result),count+1,否则(没投给result),若count为0,result更新(count不能为负数,或消耗完了投票),若count不为0,count-1;

  1. int majorityElement(vector<int>& nums) {
  2. int result=nums[0];
  3. int count=0;
  4. for(int i=1;i<nums.size();i++){
  5. if(nums[i]==result)count++;
  6. else {
  7. if(!count)result=nums[i];
  8. else count--;
  9. }
  10. }
  11. return result;
  12. }

五、轮转数组

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

法一:逐个轮转,用零时变量存被覆盖值

  1. void rotate(vector<int>& nums, int k) {
  2. int n=nums.size();
  3. k=k%n;
  4. int count=0,tmp=0,i=0,start=0;
  5. while(count<n){
  6. start=i;
  7. tmp=nums[start];
  8. do{
  9. i=(i+k)%n;
  10. swap(nums[i],tmp);
  11. count++;
  12. }while(i!=start);
  13. i++;
  14. }
  15. return;
  16. }

法二:翻转数组 

  1. void reverse(vector<int>& nums,int begin,int end){
  2. for(int i=begin,j=end;i<j;i++,j--)swap(nums[i],nums[j]);
  3. }
  4. void rotate(vector<int>& nums, int k) {
  5. int n=nums.size();
  6. reverse(nums,0,n-1);
  7. reverse(nums,0,k%n-1);
  8. reverse(nums,k%n,n-1);
  9. return;
  10. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/380508
推荐阅读
相关标签
  

闽ICP备14008679号