leetcode刷题笔记_数组和字符串

数组和字符串

数组简介

寻找数组的中心索引

给你一个整数数组 nums ,请计算数组的 中心下标 。

数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。

如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。

如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/yf47s/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    int pivotIndex(vector& nums) {
        //先算出数组所有元素的总和
        int sum=0;
        for(int i=0;i

搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

解法一:暴力法

  • 从头到尾遍历找目标值,当找到的下标对应的值比目标值还要大的时候,把目标值插入到那个位置上
class Solution {
public:
    int searchInsert(vector& nums, int target) {
        for(int i=0;itarget)
            {
                return i;
            }
        }
        return nums.size();
    }
};

解法二:二分法

class Solution {
public:
    int searchInsert(vector& nums, int target) {
        int size=nums.size();
        //如果target比最后一位都大,直接插入到最后一位
        if(target>nums[size-1])
            return size;
        int mid=size/2;
        int left=0;
        int right=size-1;
        //二分查找,如果能找到,就返回mid的位置
        while((left-1)&&(rightnums[mid])
            {
                left=mid+1;
                mid=(mid+1+right)/2;
            }
        }  
        //判断target和最后找到位置的关系,比最后位置大则返回最后位置+1
        if(target>nums[left])
             return left+1;
        //否则返回最后位置    
            return left;
    }
};

合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/c5tv3/

class Solution {
public:
    vector> merge(vector>& intervals) {
        //如果只有一个区间,返回这个区间
        if(intervals.size()==1)
            return intervals;
        //先把二维数组按每个区间的左下标排序
        sort(intervals.begin(),intervals.end());
        //定义返回结果的数组
        vector>res;
        res.push_back(intervals[0]);

        //如果当前区间的左下标小于等于当前结果数组的右下标,说明有重叠的部分可以合并
        //j记录结果数组的下标
        int j=0;
        for(int i=j+1;i

二维数组简介

旋转矩阵

给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。

不占用额外内存空间能否做到?

给定 matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

原地旋转输入矩阵,使其变为:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/clpgd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 根据数字找规律可以发现只需要沿次对角线翻转再沿水平方向中线对折即可
class Solution {
public:
    //交换两个数的值
    static void swap(int &num1,int &num2)
    {
        int temp=num1;
        num1=num2;
        num2=temp;
    }
    //交换两个数组的值
    static void swap(vector &num1,vector &num2)
    {
        vector temp=num1;
        num1=num2;
        num2=temp;
    }
    void rotate(vector>& matrix) {
        int size=matrix.size();
        //先沿次对角线两两交换位置
        for(int i=0;i

零矩阵

编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。

class Solution {
public:
    void setZeroes(vector>& matrix) {
        //记录多少行
        int LineSize=matrix.size();
        //记录多少列
        int RowSize=matrix[0].size();
        //记录列为0的元素
        vector row;
        //记录行为0的元素
        vector line;
        
        for(int i=0;i

对角线遍历

给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示

https://leetcode-cn.com/leetbook/read/array-and-string/cuxq3/

  • 实在是没想到可以这么模拟步数,写了一个下午,看到这题解的时候哭出声来
class Solution {
public:
    vector findDiagonalOrder(vector>& mat) {
       vector res;
       //定义四个方向,横着走,斜下走,往下走,斜上走
       int dx[]={0,1,1,-1};
       int dy[]={1,-1,0,1};

       int line=mat.size();
       int row=mat[0].size();

        //定义一个数组判断当前的点有没有走过
        vector>judge(line,vector(row,0));

        //记录当前的点的坐标和方向
       int x=0,y=0,d=0;

       for(int step=0;step=line||b<0||b>=row||judge[a][b]==true)
            {
                //如果d增加到超过3,那就取余,防止数组越界
                d=(d+1)%4;
                a=x+dx[d];
                b=y+dy[d];
            }
            
            //找到了下一步之后改变xy的值
            x=x+dx[d];
            y=y+dy[d];
            //如果是横着走或者竖着走的话,要先变方向,不然会一直横着走
            if(d==0||d==2)
            {
                //如果d增加到超过3,那就取余,防止数组越界
                d=(d+1)%4;
            }
       }
       return res;
      
    }
};

字符串简介

最长公共子串

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""

class Solution {
public:
    string longestCommonPrefix(vector& strs) {
        //记录最长子串
        string res;
        int len=0;
        //记录时第几个字符串
        int i=0;
        //当超过其中一个字符串的长度时,子串长度达到最大值,退出循环
        while(len

最长回文串

给你一个字符串 s,找到 s 中最长的回文子串。

class Solution {
public:
    string longestPalindrome(string s) {
        //如果字符串字符数小于等于1
        int size=s.size();
        if(s.size()<=1)
            return s;
        //要找到最长的回文子串,只需要依次求以每个字符为中心的最大子串即可
        //记录子串左下标
        int left=0;
        //记录子串的右下标
        int right=0;
        //记录最大子串的长度和下标,只要字符串不为空,最长回文串长度至少为1
        int maxlen=1;
        int pos=0;
        //从第一个下标开始依次找各个字符的最大子串
        for(int i=0;i=0&&rightmaxlen)
                {
                    maxlen=len;
                    pos=left;
                }
                left--;
                right++;
            }
            //回文串是偶数
            left=i;
            right=i+1;
             while(left>=0&&rightmaxlen) 
                {
                    maxlen=len;
                    pos=left;
                }
                left--;
                right++;
            }
        }
        return s.substr(pos,maxlen);
    }
};

翻转字符串里的单词

class Solution {
public:
    string reverseWords(string s) {
        //可以用栈来解决,读到空格就压栈   
        int left=0,right=s.size()-1;
        //先去掉左边的空格
        while(s[left]==' ')left++;
        //去掉右边空格
        while(s[right]==' ')right--;
        
        //记录当前单词
        string word;
        //栈倒叙保存单词
        stack words;
        while(left<=right)
        {
            //如果不是空的,当前单词的字母加1
            if(s[left]!=' ')
            {
                word=word+s[left];
                
            }
            //如果是空值而且左边是有字母的,整个单词压栈
            //是最后一个单词,压栈
            if((s[left]==' '&&s[left-1]!=' ')||left==right){
                words.push(word);
                word="";
            }
            //如果左边和当前字符都是空的话,直接left++
            left++;
        }
        //遍历栈输出结果字符
        string res;
        while(!words.empty())
        {
            res=res+words.top()+" ";
            words.pop();
        }
       
        return res.substr(0,res.size()-1);
        
    }
};

实现strStr()

解法一:暴力法
  • 79/80个样例超时了
class Solution {
public:
    int strStr(string haystack, string needle) {
        if(needle.size()==0)
            return 0;
        int i=0,j=0;
        while(i
解法二:改进版暴力法
  • 直接截取每一个坐标下后子串个长度的字符串比较是不是相等
class Solution {
public:
    int strStr(string haystack, string needle) {
        int haySize=haystack.size();
        int needleSize=needle.size();
        if(needleSize==0)
            return 0;
        if(haystack==needle)
            return 0;
        int i=0,j=0;
      
        //i的值最大只需要到两个字符串长度差值
        while(i
解法三:直接调库
class Solution {
public:
    int strStr(string haystack, string needle) {
        return haystack.find(needle);
    }
};

双指针技巧

反转字符串

双指针法

class Solution {
public:
    void reverseString(vector& s) {
        int left=0,right=s.size()-1;
        while(left

数组拆分

给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。

返回该 最大总和 。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/c24he/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 两个数最大的时候,他的最小值也最大,依次取最大的两个数即可
class Solution {
public:
    int arrayPairSum(vector& nums) {
        sort(nums.begin(),nums.end());
        int res=0;
        for(int i=nums.size()-2;i>=0;i=i-2)
        {
            res=res+nums[i];
        }
        return res;
    }
};

两数之和

给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/cnkjg/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解法一:哈希表
class Solution {
public:
    vector twoSum(vector& numbers, int target) {
        //如果两个数的和是target,那target-其中一个数等于另一个数
        mapmp;
        for(int i=0;i
解法二:双指针
class Solution {
public:
    vector twoSum(vector& numbers, int target) {
        int left=0;
        int right=numbers.size()-1;
        while(left

移动元素

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

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

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

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/cwuyj/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int fast=0;
        int slow=0;
        int size=nums.size();
        while(fast

最大连续1的个数

给定一个二进制数组, 计算其中最大连续 1 的个数。

class Solution {
public:
    int findMaxConsecutiveOnes(vector& nums) {
        int fast=0;
        //为了防止一开始的连续1是最大的,先将慢指针置为-1
        int slow=-1;
        int res=0;
        int curRes=0;
        while(fastcurRes?res:curRes;
                curRes=0;
                
            }           
            if(nums[fast]==0)
            {
                //如果快指针指向的数字是0,慢指针指向当前下标
                slow=fast;
                
               
            }
            fast++;
        }
        return res;

    }
};

长度最小的子数组

解法一:暴力法
class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int res=1000000;
        int curlen=0;
        
        int sum=0;
        int size=nums.size();
        for(int i=0;i=target)
                {
                    curlen=j-i+1;
                    res=res

小结

杨辉三角

给定一个非负整数 *numRows,*生成杨辉三角的前 numRows 行。

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

输入: 5
输出:
[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]
class Solution {
public:
    vector> generate(int numRows) {
        vector>res;
        //遍历从第一行到第五行
        for(int i=0;i line(i+1,0);
            for(int j=0;j

杨辉三角Ⅱ

给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。

在杨辉三角中,每个数是它左上方和右上方的数的和。

  • 笨办法,把整个杨辉三角都遍历一遍
class Solution {
public:
    vector getRow(int rowIndex) {
        vector>res;
        //遍历从第一行到第33行
        for(int i=0;i<=33;i++)
        {
            //遍历往每一行中添加元素,第i行有i+1个元素
            vector line(i+1,0);
            for(int j=0;j

反转字符串的单词Ⅲ

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

  • 快慢指针来反转
class Solution {
public:
    string reverseWords(string s) {
        int fast=0;
        int slow=0;
        while(fast=slow)&&(right<=fast-1))
                {
                    char temp=s[left];
                    s[left]=s[right];
                    s[right]=temp;
                    left++;
                    right--;
                }
                fast++;
                slow=fast;
            }
            //如果快指针没有指向空格,那么快指针继续往后移动
            else{
                fast++;
            }
            
        }
        //单独处理最后一个单词,他最后没有空格所以在前面不会反转
        int left=slow;
        int right=fast-1;
        while(left

寻找旋转排序数组的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/c3ki5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    int findMin(vector& nums) {
        int temp=nums[0];
        //只需要找到一个比第一个元素小的元素说明就是最小的,因为数组是升序的
        for(int i=0;i

删除排序数组的重复项

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/array-and-string/cq376/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 快慢指针
class Solution {
public:
    int removeDuplicates(vector& nums) {
        int size=nums.size();
        if(size==0)
            return 0;
        int fast=1;
        int slow=0;
        
        //从头到尾遍历,每次找到一个不重复的数就把慢指针指向的下一个数字改了
        for(fast=0;fast

移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

class Solution {
public:
    void moveZeroes(vector& nums) {
       //遇到非零就把零和非零换位置
        int slow=0;
        int fast=0;
        for(;fast

你可能感兴趣的:(leetcode,数据结构)