Leetcode刷题(一)

Leetcode刷题总结(1)

(之前的没有总结,后面都记录一下,刷题上瘾哈!!!)
数组篇

  1. 最小操作次数使数组元素相等

今日收获:当问题复杂时可以考虑其对立事件
语法上:
*min_element(nums.begin(),nums.end());
可以求最小数,最大同理
C++11新特性:遍历数组:for(auto & num:nums)
注意引用与不引用的区别,引用遍历可以修改数组

  1. 非递减数列

is_sorted() 函数,此函数专门用于判断某个序列是否为有序序列。
可以尝试贪心算法;
考虑情况,定位到要改的数,改前还是改后。

  1. 杨辉三角

注意vector<vector< int >>v(numRows);二维数组,分配空间。
vectorv;与vectorv(n);区别:
1. vector< int >v,插入元素v.push_back(i); 声明一个容器v时,如果没有给他预定存储空间,则可以直接使用v.push_back(x)插入变量x,那么插入的第一个元素可以用v[0]访问到。
2.vector< int >v(n)插入元素是v[i]=x;使用 vector< int > v(n); 声明一个容器v时,如果给他预定存储空间则vector< int > v(n) 等价于vector v(n,0); 如果要使得位置0存储元素x,则只能使用v[0]=x,如果使用v.insert(x)插入变量x,那么v的第一个元素还是0,即v[0]=0,因为v.push_back(x)是将x插入到v[n],又因为声明v时,v最多能存储n个元素,即x根本没有成功插入容器v中。

v[i].resize(i+1);分配空间,i+1个元素,

贪心算法

  1. 用最少数量的箭引爆气球

c++11新特性 lamada表达式的使用以及二维数组排序

sort(points.begin(),points.end(),[](vector<int>&a,vector<int>&b){
           return a[1]<b[1];

双指针

  1. 合并两个有序数组

这里我们使用了 ++ 和–的小技巧:a++ 和 ++a 都是将 a 加 1,但是 a++ 返回值为 a,而++a 返回值为 a+1。如果只是希望增加 a 的值,而不需要返回值,则推荐使用 ++a,其运行速度会略快一些。

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int pos=m-- + n-- - 1;
        while(m >= 0 && n >=0){
            nums1[pos--]=nums1[m]>nums2[n]?nums1[m--]:nums2[n--];
        } 
        while(n>=0){
            nums1[pos--]=nums2[n--];
        }
    }
};

其中int pos=m-- + n-- - 1;防止数组越界。等价于以下写法:

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int l=m-1;
        int r=n-1;
        int k=m +n -1;
        
        while(m=l>=0&&r>=0)
        {
           nums1[k--]=nums1[l]>nums2[r]?nums1[l--]:nums2[r--];           
                    
        }
         while(r>=0)
        {
            nums1[k--]=nums2[r--];
        }
       
    }
};
  1. 平方数之和
 long r=(int)sqrt(c);
  • sqrt是开方,返回数据类型为double,因此进行强制类型转换。

  • 在枚举 aa 的同时,使用 \texttt{sqrt}sqrt 函数找出 bb。注意:本题 cc 的取值范围在 [0,2^{31} - 1]
    [0,2^31 −1],因此在计算的过程中可能会发生 int 型溢出的情况,需要使用 long 型避免溢出。

  1. 验证回文字符串 Ⅱ
  • 灵活使用bool类型,注意字符串操作用法。
class Solution {
public:
    bool validPalindrome(string s) {
        int left = 0;
        int right = s.length() - 1;
        while (left < right) {
            if (s[left] == s[right]) {
                left++;
                right--;
            } else {
                return (check(left, right - 1, s) || check(left + 1, right, s));
            }
        }
        return true;
    }

    bool check(int left, int right, string &s) {
        while (left < right) {
            if (s[left] != s[right]) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};
  1. 通过删除字母匹配到字典里最长单词
  • lamada匿名函数的使用,用&可以加快运算效率,a.size()和a.length()没什么区别。
class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n=t.length();
        int m=s.length();
        int l=0;
        int r=0;
        while(l<m&&r<n)
        {
            if(s[l]==t[r])
            {
                r++;
            }
            l++;
        }
        return r==n;

    }
    string findLongestWord(string s, vector<string>& dictionary) {
        sort(dictionary.begin(),dictionary.end(),[&](string &a,string &b){
            if(a.size()==b.size())
            {
                return a<b;
            }
            return a.size()>b.size();
        });
        int k=dictionary.size();
       
        for(int i=0;i<k;i++)
        {
            if(isSubsequence(s,dictionary[i]))
            {
                return dictionary[i];
            }
           
        }
        return "";

    }
};

二分查找法

  1. 二分查找
  • 考虑区间开闭,经常用其思想,变种使用
  • 一般使用与给定数组有序,时间复杂度为logn
 int search(vector<int>& nums, int target) {
        int n=nums.size();
        int l=0;
        int r=n-1;
        while(l<=r)
        {
            int mid=l+(r-l)/2;
            if(nums[mid]<target)
            {
                l=mid+1;
            }
            else if(nums[mid]>target)
            {
                r=mid-1;
            }
            else{
                return mid;
            }
        }
        return -1;

前缀和的思想,补一个位子

  1. 区域和检索 - 数组不可变
class NumArray {
public:
    vector<int> array;
    NumArray(vector<int>& nums) {
        array.resize(nums.size()+1);
        for(int i=0;i<nums.size();++i){
            array[i+1]=nums[i]+array[i];
        }
    }
    
    int sumRange(int left, int right) {
        return array[right+1]-array[left];
    }
};

在这里插入图片描述

  1. 有序数组中的单一元素
  • 利用按位异或的性质,可以得到mid 和相邻的数之间的如下关系,其中 \oplus⊕ 是按位异或运算符:
  • 当 mid 是偶数时,mid+1=mid⊕1;
    当 mid 是奇数时,mid−1=mid⊕1。

例如:
4^1=5
3^1=2

因此在代码中直接使用了mid 和 mid^1 作为进行比较的两个下标,不需要再判断 mid 的奇偶性,代码更加简洁。

  • 考虑mid 和 1 按位与运算的结果,其中 & 是按位与运算符:

当mid 是偶数时,mid & 1=0;

当 mid 是奇数时, mid & 1=1。

因此在得到mid 的值之后,将mid 的值减去mid & 1,即可确保 mid 是偶数,如果原来的mid 是偶数则值不变,如果原来的mid 是奇数则值减 1。

class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        int low = 0, high = nums.size() - 1;
        while (low < high) {
            int mid = (high - low) / 2 + low;
            mid -= mid & 1;
            if (nums[mid] == nums[mid + 1]) {
                low = mid + 2;
            } else {
                high = mid;
            }
        }
        return nums[low];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值