Leetcode打卡——数组和字符串(共22题)

Leetcode 专栏收录该内容
31 篇文章 0 订阅

集合:

定义
由一个或多个确定的元素所构成的整体。
特性
1.集合里的元素类型不一定相同。
2.集合里的元素没有顺序。
事实上,这样的集合并不直接存在于编程语言中。然而,实际编程语言中的很多数据结构,就是在集合的基础上添加了一些规则形成的。

列表(线性列表)

定义:
一种数据项构成的有限序列,即按照一定的线性顺序,排列而成的数据项的集合。
列表的概念是在集合的特征上形成的,它具有顺序,且长度是可变的。
列表最常见的表现形式有数组和链表,而我们熟悉的栈和队列则是两种特殊类型的列表。

数组

如何从宏观上区分列表和数组呢?这里有一个重要的概念:索引
1.数组会用一些名为索引的数字来标识每项数据在数组中的位置,且在大多数编程语言中,索引是从 0 算起的。我们可以根据数组中的索引,快速访问数组中的元素。列表中没有索引,这是数组与列表最大的不同点。
2.数组中的元素在内存中是连续存储的,且每个元素占用相同大小的内存。列表中的元素在内存中可能彼此相邻,也可能不相邻。比如列表的另一种实现方式——链表,它的元素在内存中则不一定是连续的

1.Leetcode724.寻找数组的中心下标

在这里插入图片描述
前缀和

class Solution {
public:
    int pivotIndex(vector<int>& nums) {
        int a[10100];
        memset(a,0,sizeof a);
        int len=nums.size();
        for(int i=1;i<=len;i++){         
            a[i]=a[i-1]+nums[i-1];
        }
        
        for(int i=1;i<=len;i++){
            if(a[i-1]==a[len]-a[i]){
                return i-1;
            }
        }
        return -1;
    }
};

2.Leetcode35.搜索插入位置

在这里插入图片描述

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int len=nums.size();
        int l=0,r=len-1;
        while(l<r){
            int mid=(l+r)/2;
            if(nums[mid]>=target){
                r=mid;
            }else{
                l=mid+1;
            }
        }
        if(l==len-1&&target>nums[l])return l+1;
        return l;
    }
};

3.Leetcode56.合并区间

在这里插入图片描述

const int INF=-0x3f3f3f3f;
class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>>ans;
        sort(intervals.begin(),intervals.end());
        int len=intervals.size();
        int begin,end;
         for(int i=0;i<len;i++){
             vector<int>line;
             int a=intervals[i][0],b=intervals[i][1];
             if(!i){
                 begin=a;
                 end=b;
             }
             if(i&&a>end){
                line.push_back(begin);
                line.push_back(end);
                ans.push_back(line);
                begin=a;
                end=b;   
             }else if(i&&a<=end){
                 end=max(end,b);
             }
             if(i==len-1){
                 vector<int>tail;
                 tail.push_back(begin);
                 tail.push_back(end); 
                 ans.push_back(tail);
             }
             
             
         }
         return ans;
    }
};

二维数组

只是将数组中的每个元素变成了一维数组
二维数组的本质上仍然是一个一维数组,内部的一维数组仍然从索引 0 开始,我们可以将它看作一个矩阵,并处理矩阵的相关问题。
在这里插入图片描述

4.面试题 01.07. 旋转矩阵

在这里插入图片描述

class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int len=matrix.size();
       
        for(int i=0;i<len;i++){
            for(int j=0;j<i;j++){
                swap(matrix[i][j],matrix[j][i]);
            }
        }
        
        for(int i=0;i<len;i++){
            for(int j=0;j<len/2;j++){
                swap(matrix[i][j],matrix[i][len-j-1]);
            }
        }
             
    }
};

5.面试题 01.08. 零矩阵

在这里插入图片描述

法一:标记数组
最容易想到了就不写了

法二:使用两个标记变量
我们可以用矩阵的第一行和第一列代替方法一中的两个标记数组,以达到 O(1)O(1) 的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 00。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含 00。

在实际代码中,我们首先预处理出两个标记变量,接着使用其他行与列去处理第一行与第一列,然后反过来使用第一行与第一列去更新其他行与列,最后使用两个标记变量更新第一行与第一列即可。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int n=matrix.size();
        int m=matrix[0].size();
        bool row=false,col=false;
        for(int i=0;i<m;i++){
            if(!matrix[0][i]){
                row=true;
                break;
            }
        }
        for(int i=0;i<n;i++){
            if(!matrix[i][0]){
                col=true;
                break;
            }
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(!matrix[i][j])matrix[0][j]=matrix[i][0]=0;
            }
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(!matrix[0][j]||!matrix[i][0])matrix[i][j]=0;
            }
        }
        if(row){
            for(int i=0;i<m;i++){
                matrix[0][i]=0;
            }
        }
         if(col){
            for(int i=0;i<n;i++){
                matrix[i][0]=0;
            }
        }
    }
};

法三:使用一个标记变量
我们可以对方法二进一步优化,只使用一个标记变量记录第一列是否原本存在 00。这样,第一列的第一个元素即可以标记第一行是否出现 00。但为了防止每一列的第一个元素被提前更新,我们需要从最后一行开始,倒序地处理矩阵元素。

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int n=matrix.size();
        int m=matrix[0].size();
        bool col=false;
        //注意先列再行不然行matrix[0][0]的改变会影响到列
        for(int i=0;i<n;i++){
            if(!matrix[i][0]){
                col=true;
                break;
            }
        }
        for(int i=0;i<m;i++){
            if(!matrix[0][i]){
                matrix[0][0]=0;
                break;
            }
        }
        
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(!matrix[i][j])matrix[0][j]=matrix[i][0]=0;
            }
        }
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(!matrix[0][j]||!matrix[i][0])matrix[i][j]=0;
            }
        }
        if(matrix[0][0]==0){
            for(int i=0;i<m;i++){
                matrix[0][i]=0;
            }
        }
         if(col){
            for(int i=0;i<n;i++){
                matrix[i][0]=0;
            }
        }
    }
};

6.Leetcode498. 对角线遍历

直接模拟
在这里插入图片描述

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& mat) {
          vector<int>ans;
          int n=mat.size(),m=mat[0].size();     
          bool flag=true;
          int pre;
          pre=0;
          int len=m+n;
          for(int i=0;i<len*2-1;i++){
             if(flag){
                 int row=pre;
                 int col=i-pre; 
                 int b=2*len-i;    
                 while(!(row>=0&&row<n&&col>=0&&col<m)&&b--){
                   row--;
                   col++;             
                 }    
                 while(row>=0&&row<n&&col>=0&&col<m){
                     ans.push_back(mat[row--][col++]);
                 }              
                 pre=col;
             }else{
                 int row=i-pre;
                 int col=pre;
                 int b=2*len-1-i;
                 while(!(row>=0&&row<n&&col>=0&&col<m)&&b--){
                    row++;
                    col--;
                 }
                 while(row>=0&&row<n&&col>=0&&col<m){
                     ans.push_back(mat[row++][col--]);
                 }
                 pre=row;
             }
             flag=!flag;
          }         
          return ans;
    }
};

7.Leetcode14. 最长公共前缀

在这里插入图片描述
法一:横向扫描暴力解

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
         string ans;
         int len=strs.size();
         int n=strs[0].size();
         for(int i=0;i<n;i++){
            auto c=strs[0][i];
            int j;
           for(j=1;j<len;j++){
              if(c!=strs[j][i])break;
           }
           if(j==len){
               ans+=c;
           }else{
               return ans;
           }
         }
         return ans;
    }
};

法二:
看了大佬的解法,超级巧妙
字典排序后,第一个串与最后一个串差异最大,找他们两的公共前缀,就是所有子串的公共前缀

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
         string ans;
         sort(strs.begin(),strs.end());
         string st=strs[0],end=strs[strs.size()-1];
         int len1=st.size(),len2=end.size();
         int t=0;
         while(t<len1&&t<len2&&st[t]==end[t]){
             ans+=st[t];
             t++;
         }
         return ans;
    }
};

8.Leetcode5. 最长回文子串

在这里插入图片描述

法一:暴力法,直接超时

class Solution {
public:
    string longestPalindrome(string s) {
       int len=s.size();
       if(len<2)return s;
       int begin=0;
       int maxlen=1;
       
       for(int i=0;i<len-1;i++){
           for(int j=i+1;j<len;j++){
               if(j-i+1>maxlen&&check(i,j,s)){
                   maxlen=j-i+1;
                   begin=i;
               }
           }
       }
       printf("%d",maxlen);
       return s.substr(begin,maxlen);
    }
    bool check(int i,int j,string s){
        int len=(j-i)/2;
        for(int k=0;k<=len;k++){
            if(s[i+k]!=s[j-k]){
                return false;
                
            }
        }
        return true;
    }
};

法二:动态规划

const int N=1010;
class Solution {
public:
    bool dp[N][N];
    string longestPalindrome(string s) {
        int len=s.size();
        if(len<2||len==2&&(s[0]==s[1]))return s;
         int begin=0,end=0;
         memset(dp,0,sizeof dp);
         for(int i=0;i<len;i++){
             dp[i][i]=true;     
             if(i+1<len&&s[i]==s[i+1]){
                 dp[i][i+1]=true;
                 begin=i;
                 end=i+1;
             }
         }
        
         for(int k=2;k<len;k++){
             for(int i=0;i<len;i++){
                if(i+k==len)break;
                if(s[i]==s[i+k]&&dp[i+1][i+k-1]){
                    dp[i][i+k]=true;
                    if(k>end-begin){
                        begin=i;
                        end=i+k;
                    }
                }
             }
         }
         
         return s.substr(begin,end-begin+1);

    }
};

法三:中心扩展法

const int N=1010;
typedef pair<int,int>PII;
class Solution {
public:
    string longestPalindrome(string s) {
       int len=s.size();
       if(len==0||len==1)return s;
       PII ans={0,0};
       for(int i=0;i<len;i++){
          auto t=check(i,i,s);
          if(t.second-t.first>ans.second-ans.first){
              ans=t;
          }
          t=check(i,i+1,s);
          if(t.second-t.first>ans.second-ans.first){
              ans=t;
          }
       }
       
       return s.substr(ans.first,ans.second-ans.first+1);
    }
    PII check(int i,int j,string s){
        PII ans;
        int len=s.size();
        int l=i,r=j;
        while(s[l]==s[r]){  
            ans={l,r};  
            l--;
            r++;
            if(l<0||l>=len||r<0||r>=len)break;
        }
        
        return ans;
       
    }
};

9.Leetcode151. 翻转字符串里的单词

在这里插入图片描述
注意要去掉多余的空格

class Solution {
public:
    string reverseWords(string s) {
        int i=0,j=s.size()-1;
        while(s[i]==' ')i++;
        while(s[j]==' ')j--;
        s=s.substr(i,j+1-i);
        
        
        for(int i=0;i<s.size();i++){
           int j=i;
           while(j<s.size()&&s[j]!=' ')j++;
           reverse(s.begin()+i,s.begin()+j);
           if(j==s.size())break;
           int p=j;
           while(s[p+1]==' ')p++;
           if(p!=j)s=s.substr(0,j+1)+s.substr(p+1,s.size()-p-1);
           i=j;
        }
        reverse(s.begin(),s.end());
        
        return s;
    }
};

10.Leetcode28. 实现 strStr()

在这里插入图片描述

KMP

class Solution {
public:
    int strStr(string haystack, string needle) {
       int n=haystack.size();
       int m=needle.size();
       if(n==0&&m>0)return -1;
       if((n==0||m==0)||haystack==needle)return 0;

       int ans=0;
       const int N=5e4+10;
       int ne[N];
       memset(ne,0,sizeof ne);
       bool flag=false;

       haystack=" "+haystack;
       needle=" "+needle;
       
       for(int i=2,j=0;i<=m;i++){
           while(j&&needle[i]!=needle[j+1])j=ne[j];
           if(needle[i]==needle[j+1])j++;
           ne[i]=j;
       }
       for(int i=1,j=0;i<=n;i++){
           while(j&&haystack[i]!=needle[j+1])j=ne[j];
           if(haystack[i]==needle[j+1])j++;
           if(j==m){
              ans=i-m;
              flag=true;
              break;
           }

       }
       if(!flag)return -1;
       return ans;
    }
};

11.Leetcode344. 反转字符串

在这里插入图片描述

class Solution {
public:
    void reverseString(vector<char>& s) {
        int len=s.size();
        for(int i=0;i<len/2;i++){
            swap(s[i],s[len-i-1]);
        }
    }
};

12.Leetcode561. 数组拆分 I

在这里插入图片描述
直接排序,两个一组

class Solution {
public:
    int arrayPairSum(vector<int>& nums) { 
        int len=nums.size();
        quicksort(0,len-1,nums);
        int ans=0;
        for(int i=0;i<len;i+=2){
           ans+=nums[i];
        }
        return ans;
    }
    void quicksort(int l,int r,vector<int>&nums){
        if(l==r)return;
        int x=nums[l],i=l-1,j=r+1;
        while(i<j){
            do{i++;}while(nums[i]<x);
            do{j--;}while(nums[j]>x);
            if(i<j)swap(nums[i],nums[j]);
        }
        quicksort(l,j,nums);
        quicksort(j+1,r,nums);
    }
};

13.Leetcode167. 两数之和 II - 输入有序数组

在这里插入图片描述

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int>ans;
       int len=numbers.size();
       int i=0,j=len-1;
       int prei=0,prej=len-1;
      
       while(i<=j){
          if(numbers[i]+numbers[j]==target){
              ans.push_back(i+1);
              ans.push_back(j+1);
              break;
          }else if(numbers[i]+numbers[j]<target){
              i++;
              if(i==prei)break;
              prei=i;
              
          }else{
              j--;
              if(j==prej)break;
              prej=j;
          }
       }
       return ans;
    }
};

14.Leetcode27. 移除元素

在这里插入图片描述
快慢指针

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len=nums.size();
        int j=0;
        for(int i=0;i<len;i++){
            if(nums[i]!=val)nums[j++]=nums[i];
        }
        return j;
    }
};

15.Leetcode485. 最大连续 1 的个数

在这里插入图片描述

class Solution {
public:
    int ans=0;
    int findMaxConsecutiveOnes(vector<int>& nums) {
        int len=nums.size();
        for(int i=0;i<len;i++){
            int j=i;
            while(j<len&&nums[j]==1)j++;
            ans=max(ans,j-i);
            if(i!=j)i=j-1;
        }
        return ans;
    }
};

16.Leetcode209. 长度最小的子数组

在这里插入图片描述

class Solution {
public:
    const int MAX=0x3f3f3f3f;
    int ans=MAX;
    int minSubArrayLen(int target, vector<int>& nums) {
        int len=nums.size();
        for(int i=0;i<len;i++){
            int j=i,sum=0;
            while(j<len&&sum<target){
               sum+=nums[j++];
            }
            if(j==len&&sum<target)break;
            if(sum>=target&&j-i!=0)ans=min(ans,j-i);
        }
        if(ans==MAX)return 0;
        return ans;
        
        
    }
};

17.Leetcode118. 杨辉三角

在这里插入图片描述

class Solution {
public:
    vector<vector<int>>ans; 
    vector<int>line;
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>>ans=dfs(1,numRows);
        return ans;
    }
    vector<vector<int>>dfs(int row,int end){
        vector<int>preline=line;
        line.clear();
        if(row==1){
           line.push_back(1); 
        }else if(row==2){
            line.push_back(1);
            line.push_back(1);
        }else{
            int len=preline.size();
            line.push_back(1);
            for(int i=0;i<len-1;i++){
                line.push_back(preline[i]+preline[i+1]);
            }
            line.push_back(1);
        }
        ans.push_back(line);
        if(row<end)dfs(row+1,end);
        return ans;
    }
};

18.Leetcode119. 杨辉三角 II

在这里插入图片描述

class Solution {
public:
    vector<int>line;
    vector<int> getRow(int numRows) {
        vector<int>ans=dfs(1,numRows+1);
        return ans;
    }
    vector<int>dfs(int row,int end){
        vector<int>preline=line;
        line.clear();
        if(row==1){
           line.push_back(1); 
        }else if(row==2){
            line.push_back(1);
            line.push_back(1);
        }else{
            int len=preline.size();
            line.push_back(1);
            for(int i=0;i<len-1;i++){
                line.push_back(preline[i]+preline[i+1]);
            }
            line.push_back(1);
        }
        if(row<end)dfs(row+1,end);
        return line;
    }
};

19. Leetcode557. 反转字符串中的单词 III

在这里插入图片描述

class Solution {
public:
    string reverseWords(string s) {
        int len=s.size();
        for(int i=0;i<len;i++){
            int j=i;
            while(j<len&&s[j]!=' ')j++;
            reverse(s.begin()+i,s.begin()+j);
            i=j;
        }
        return s;
    }
};

20.Leetcode153. 寻找旋转排序数组中的最小值

在这里插入图片描述

class Solution {
public:
    int findMin(vector<int>& nums) {
       int len=nums.size();
       int l=0,r=len-1;
       int high=nums[len-1];
       while(l<r){
           int mid=(l+r)/2;
           if(nums[mid]<=high){
               r=mid;
           }else{
               l=mid+1;
           }
       }
       return nums[l];
    }
};

21.Leetcode26. 删除有序数组中的重复项

在这里插入图片描述

class Solution {
public:
    
    int removeDuplicates(vector<int>& nums) {
        int len=nums.size(),j=0;

        for(int i=0;i<len;i++){
           if(j==0||nums[i]!=nums[j-1]){
               nums[j++]=nums[i];              
           }
     
        }
        return j;
    }

};

22.Leetcode283. 移动零

在这里插入图片描述

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int len=nums.size(),j=0;
        for(int i=0;i<len;i++){
            if(nums[i]!=0){
               nums[j++]=nums[i];
            }
        }
        for(int i=j;i<len;i++){
            nums[i]=0;
        }
    }
};
©️2022 CSDN 皮肤主题:游动-白 设计师:白松林 返回首页

打赏作者

被折叠的小饼干

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值