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

集合:

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

列表(线性列表)

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

数组

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

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

Leetcode打卡——数组和字符串(共22题)_第1张图片
前缀和

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.搜索插入位置

Leetcode打卡——数组和字符串(共22题)_第2张图片

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.合并区间

Leetcode打卡——数组和字符串(共22题)_第3张图片

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 开始,我们可以将它看作一个矩阵,并处理矩阵的相关问题。
Leetcode打卡——数组和字符串(共22题)_第4张图片

4.面试题 01.07. 旋转矩阵

Leetcode打卡——数组和字符串(共22题)_第5张图片

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. 零矩阵

Leetcode打卡——数组和字符串(共22题)_第6张图片

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

法二:使用两个标记变量
我们可以用矩阵的第一行和第一列代替方法一中的两个标记数组,以达到 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. 对角线遍历

直接模拟
Leetcode打卡——数组和字符串(共22题)_第7张图片

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. 最长公共前缀

Leetcode打卡——数组和字符串(共22题)_第8张图片
法一:横向扫描暴力解

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. 最长回文子串

Leetcode打卡——数组和字符串(共22题)_第9张图片

法一:暴力法,直接超时

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. 翻转字符串里的单词

Leetcode打卡——数组和字符串(共22题)_第10张图片
注意要去掉多余的空格

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()

Leetcode打卡——数组和字符串(共22题)_第11张图片

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. 反转字符串

Leetcode打卡——数组和字符串(共22题)_第12张图片

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

Leetcode打卡——数组和字符串(共22题)_第13张图片
直接排序,两个一组

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 - 输入有序数组

Leetcode打卡——数组和字符串(共22题)_第14张图片

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. 移除元素

Leetcode打卡——数组和字符串(共22题)_第15张图片
快慢指针

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 的个数

Leetcode打卡——数组和字符串(共22题)_第16张图片

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. 长度最小的子数组

Leetcode打卡——数组和字符串(共22题)_第17张图片

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. 杨辉三角

Leetcode打卡——数组和字符串(共22题)_第18张图片

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

Leetcode打卡——数组和字符串(共22题)_第19张图片

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

Leetcode打卡——数组和字符串(共22题)_第20张图片

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. 寻找旋转排序数组中的最小值

Leetcode打卡——数组和字符串(共22题)_第21张图片

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. 删除有序数组中的重复项

Leetcode打卡——数组和字符串(共22题)_第22张图片

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. 移动零

Leetcode打卡——数组和字符串(共22题)_第23张图片

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;
        }
    }
};

你可能感兴趣的:(Leetcode,leetcode,算法,链表)