面试经典150题:数组/字符串合集

这篇具有很好参考价值的文章主要介绍了面试经典150题:数组/字符串合集。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

新专栏,预计两个月写完吧,每天下班回来抽空做几道题。会把做题计划顺序记录下来,如果你有缘,刷到这个开篇序列,那就跟着文章去练题吧。初学者可以慢慢来

88. 合并两个有序数组

    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int i=m-1;
        int j=n-1;
        int k=m+n-1;
        //从后往前插
        while(j>=0)
        {
            if(i>=0&&nums1[i]>nums2[j])
            {
                nums1[k--]=nums1[i];
                i--;
            }
            else{
                nums1[k--]=nums2[j];
                j--;
            }
        }
        
    }

27. 移除元素

这是前后指针覆盖做的,也可以双向指针交换做,思路 i从0开始,j从尾巴开始,如果i的值不等于val那就++,如果等于了就和j的值交换,j--,i不变,下一轮再交换来的i还是不是val,是的话继续交换,j--,这样循环

    int removeElement(vector<int>& nums, int val) {
        int i=0,j=0;
        while(j<nums.size())
        {
            if(nums[j]!=val)
            {
                nums[i]=nums[j];
                j++;
                i++;
            }
            else{
                j++;
            }
        }
        return i;
    }

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

    int removeDuplicates(vector<int>& nums) {
        int i=0,j=0;
        while(j<nums.size())
        {
            if(nums[i]==nums[j])
            {
                j++;
            }
            else{
                ++i;
                nums[i]=nums[j];
                j++;
            }
        }
        return i+1;
    }

80. 删除有序数组中的重复项 II

    int removeDuplicates(vector<int>& nums) {
        int i=0,j=0;
        while(j<nums.size())
        {
            if(i<2||nums[j]!=nums[i-2])
            {
                nums[i++]=nums[j];
            }
            j++;

        }
        return i;
    }

169. 多数元素

方法太多了,我写三个就行

    int majorityElement(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        return nums[nums.size()/2];
    }


    int majorityElement(vector<int>& nums) {
        unordered_map<int,int>mp;
        int ans=0;
        for(const auto &x:nums)
        {
            mp[x]++;
            if(mp[x]>nums.size()/2){
                ans=x;
            }
        }
        return ans;
    }


    摩尔投票法只满足超过一半的投票,符合题意
    玩的就是票数抵消,留下存活的那个
    int majorityElement(vector<int>& nums) {
        //摩尔投票法,一种很奇妙的思路
        int candition=0;//候选人
        int vote=0;//票数
        for(auto x:nums)
        {
            if(vote==0)candition=x;
            if(x==candition)vote++;
            if(x!=candition)vote--;
        }
        return candition;

    }

189. 轮转数组

第一句为了防止越界,这力扣限制服了,,写了两种方法

    void rotate(vector<int>& nums, int k) {
        k%=nums.size();
        vector<int>vv;
        vv.reserve(nums.size()*2);
        vv.insert(vv.end(),nums.begin(),nums.end());
        vv.insert(vv.end(),nums.begin(),nums.end());
        vector<int>vp(vv.begin()+nums.size()-k,vv.begin()+nums.size()*2-k);
        nums=vp;
    }

    void rotate(vector<int>& nums, int k) {
        k%=nums.size();
        reverse(nums.begin(),nums.begin()+nums.size()-k);
        reverse(nums.begin()+nums.size()-k,nums.end());
        reverse(nums.begin(),nums.end());
    }

121. 买卖股票的最佳时机

    int maxProfit(vector<int>& prices) {
        vector<vector<int>>dp(prices.size(),vector<int>(2));
        dp[0][0]=-prices[0]; //有股票
        dp[0][1]=0;  //没有股票
        for(int i=1;i<prices.size();++i)
        {
            dp[i][0]=max(-prices[i],dp[i-1][0]);
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]+prices[i]);
        }
        return dp[prices.size()-1][1];
    }

122. 买卖股票的最佳时机 II

    int maxProfit(vector<int>& prices) {

        //0 手里没股票 ,1手里有股票
        vector<vector<int>>dp(prices.size(),vector<int>(2));
        dp[0][0]=0;
        dp[0][1]=-prices[0];
        for(int i=1;i<prices.size();++i)
        {
            dp[i][1]=max(dp[i-1][0]-prices[i],dp[i-1][1]);
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);
        }
        return dp[prices.size()-1][0];
    }

55. 跳跃游戏

只要范围覆盖能到就行

    bool canJump(vector<int>& nums) {
        int n=nums.size()-1;
        int cover=0;
        for(int i=0;i<=cover;++i)
        {

            cover=max(nums[i]+i,cover);
            if(cover>=n){
                return true;
            }

        }
        return false;
    }

45.跳跃游戏2

    int jump(vector<int>& nums) {

        if(nums.size()==1){
            return 0;
        }
        int n=nums.size()-1;
        int cover=0;
        int ans=0;
        int cur=0;
        for(int i=0;i<nums.size();++i)
        {
            cover=max(i+nums[i],cover);
            
            if(i==cur){
                ans++;
                cur=cover;
                if(cover>=n)
                {
                    break;
                }
            }

        }
        return ans;
    }

274. H 指数

    int hIndex(vector<int>& citations) {
        //默认h为文章数,对引用量排序,如果小于h,将h--。
        
        int lens=citations.size();
        if(lens==0){
            return 0;
        }
        int h=lens;
        sort(citations.begin(),citations.end());
        for(auto x:citations){
            if(x<h){
                h--;
            }
        }
        return h;
    }

380. O(1) 时间插入、删除和获取随机元素

用vector的下标和map做映射

class RandomizedSet {
private:
    vector<int>vv;
    unordered_map<int,int>mp; //key->val  vaule->index
public:
    RandomizedSet() {
        srand((unsigned int)time(NULL));
    }
    
    bool insert(int val) {
        if(mp.count(val)){
            return false;
        }
        int idx=vv.size();
        mp[val]=idx;
        vv.push_back(val);
        return true;
    }
    
    bool remove(int val) {
        if(!mp.count(val)){
            return false;
        }

        int preidx=mp[val];
        int curidx=vv.size()-1;
        vv[preidx]=vv[curidx];
        
        //更新map 对应下标
        mp[vv[preidx]]=preidx;
        //删除
        vv.pop_back();
        mp.erase(val);
        return true;

    }
    
    int getRandom() {
        int idx=rand()%vv.size();
        return vv[idx];
    }
};

238. 除自身以外数组的乘积

    vector<int> productExceptSelf(vector<int>& nums) {
        
        //左乘积 * 右乘积
        int ml=1;
        vector<int>vv(nums.size(),1);
        for(int i=1;i<nums.size();++i)
        {
            ml*=nums[i-1];
            vv[i]=ml;
            
        }

        int mr=1;
        for(int i=nums.size()-2;i>=0;--i)
        {
            mr*=nums[i+1];
            vv[i]*=mr;
        }
        return vv;

    }

134.加油站

    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        
    /*     if(accumulate(gas.begin(),gas.end(),0)<accumulate(cost.begin(),cost.end(),0))
		{
			return -1;
		}*/
        //不要上面那句就加一个total 记录完整一路看有没有剩油
        int total=0;
        int cur=0;
        int index=0;
        for(int i=0;i<gas.size();++i)
        {
            total+=gas[i]-cost[i];
            cur+=gas[i]-cost[i];
            if(cur<0)
            {
                index=i+1;
                cur=0;
            }
        }   
        return total<0?-1:index;

    }

135. 分发糖果

    int candy(vector<int>& ratings) {
        //每个孩子都至少有一个糖果
        vector<int>res(ratings.size(),1);
        //从前往后,把右边分数高的糖果多一个

        for(int i=0;i<ratings.size()-1;++i)
        {
            if(ratings[i]<ratings[i+1])
            {
                res[i+1]=res[i]+1;
            }
        }

        //从后往前,把左边分数高的糖果多分一个
        //局部还要贪心,要给第i个孩子分当前糖果和右边糖果数+1的最大值
        //给到当前孩子糖果,因为这样才能保证局部此时第i个孩子的糖果,比左边右边相邻都大
        //体现到全局就是每每相邻的两个孩子,分数最大的那个一定糖果最多
        for(int i=ratings.size()-1;i>0;--i)
        {
            if(ratings[i-1]>ratings[i])
            {
                res[i-1]=max(res[i-1],res[i]+1);
            }
        }
        return accumulate(res.begin(),res.end(),0);
    }

42. 接雨水

我有篇博客详细讲了这个题的做法,用了五种方法

这块我演示三种推荐的

找到最高点,左右两边,求雨水

 int trap(vector<int>& height) {
        
       
        int ans=0;
        int value=0;
        int index=0;
        for(int i=0;i<height.size();++i)
        {
            if(height[i]>value){
                value=height[i];
                index=i;
            }
        }
        int st=0;
        for(int i=0;i<index;++i)
        {
            if(height[i]>st){
                st=height[i];
            }
            else{
                ans+=st-height[i];
            }
        }
        st=0;
        for(int i=height.size()-1;i>index;--i)
        {
            if(height[i]>st){
                st=height[i];
            }
            else{
                ans+=st-height[i];
            }
        }
        return ans;
    }

双指针

int trap(vector<int>& height) {
        
        int left=0;
        int right=height.size()-1;
        int ans=0;
        int mlhi=height[0];
        int rlhi=height[height.size()-1];
        while(left<right)
        {
            mlhi=max(mlhi,height[left]);
            rlhi=max(rlhi,height[right]);
            if(mlhi>rlhi){
                ans+=rlhi-height[right];
                right--;
            }
            else{
                ans+=mlhi-height[left];
                left++;
            }
        }
        return ans;
    }

单调栈 递减

 int trap(vector<int>& height) {
        stack<int>sk;
        sk.push(0);
        int ans=0;
        for(int i=1;i<height.size();++i)
        {
            while(!sk.empty()&&height[i]>height[sk.top()])
            {
                int righthright=height[i];
                int curheight=height[sk.top()];
                sk.pop();
                if(!sk.empty())
                {
                int leftheight=height[sk.top()];
                int chang=i-sk.top()-1;
                int gao=min(righthright,leftheight)-curheight;
                ans+=chang*gao;
                }

            }
            sk.push(i);
        }
        return ans;
    }

13. 罗马数字转整数

 int romanToInt(string s) {
        int res=0;
        for(int i=0;i<s.size();++i)
        {
            if(s[i]=='V')res+=5;
            else if(s[i]=='L')res+=50;
            else if(s[i]=='D')res+=500;
            else if(s[i]=='M')res+=1000;
            else if(s[i]=='I'){ //一点代码技巧
                 res=s[i+1]=='V'||s[i+1]=='X'?res-1:res+1;
            }
            else if(s[i]=='X'){
                res=s[i+1]=='L'||s[i+1]=='C'?res-10:res+10;
            }
            else{
                 res=s[i+1]=='D'||s[i+1]=='M'?res-100:res+100;
            }
        }
        return res;
    }

12.整数转罗马数字

    string intToRoman(int num) {
        //哈希
        int arr[]{1000,900,500,400,100,90,50,40,10,9,5,4,1};
        string btr[]{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        string ans="";
        for(int i=0;i<sizeof(arr)/sizeof(arr[0]);++i)
            {
                while(num>=arr[i])
                {
                    num-=arr[i];
                    ans+=btr[i];
                }
            }
        
        return ans;
    }

58. 最后一个单词的长度

    int lengthOfLastWord(string s) {
       
        int count=0;
        int i=s.size()-1;

        for(i;i>=0;)
        {
            if(count&&s[i]==' ')
            {
                break;
            }
            if(s[i]==' ')
            {
                i--;
            }
            else{
                count++;
                i--;
            }
            
        }
        return count;

    }

14. 最长公共前缀

学习minmax_element

    string longestCommonPrefix(vector<string>& strs) {
        if(strs.empty())return "";
        auto p=minmax_element(strs.begin(),strs.end());

        for(int i=0;i<p.first->size();++i)
        {
            if(p.first->at(i)!=p.second->at(i))
            {
                return p.first->substr(0,i);
            }
        }
        return *p.first;

    }
    string longestCommonPrefix(vector<string>& strs) {
        //纵向对比,横向去扫描
        //abcf
        //ab
        //abs
        
        if(strs.empty()){
            return "";
        }
        string res="";
        for(int j=0;j<strs[0].size();++j)
        {
            for(int i=0;i<strs.size();++i)
            {
                if(strs[0][j]!=strs[i][j])
                {
                    return res;
                }  
            }
            res+=strs[0][j];
        }
        return res;
    }

151. 反转字符串中的单词

直接重构字符串,,不用erase去写了,erase版本好麻烦写起来

    string reverseWords(string s) {

        //重构字符串,去重多余空格
        int slow=0;
        for(int i=0;i<s.size();++i)
        {
            if(s[i]!=' ')
            {
               
                if(slow!=0) //处理中间,只放一个空格
                {
                    s[slow++]=' ';
                } 
                while(s[i]!=' '&&i<s.size())

                {
                    s[slow++]=s[i++];
                }
            }
        }
        s.resize(slow);
        int j=0;
        for(int i=0;i<s.size();++i)
        {
            if(s[i]==' ')
            {
                reverse(s.begin()+j,s.begin()+i);
                j=i+1;
            }
        }
        reverse(s.begin()+j,s.end());
        reverse(s.begin(),s.end());
        return s;
    }

 

6. N 字形变换 

    string convert(string s, int numRows) {
        string  res="";
        if(numRows==1)return s;
        vector<string>vv(numRows);
        int k=0;
        int flg=1;//标志转向
        for(int i=0;i<s.size();++i)
        {
           vv[k]+=s[i];
           if(k==0||k==numRows-1)
            {
                flg*=-1;
            }
            k+=flg>0?-1:1;
           
        }
         for(auto x:vv)
         {
             res+=x;
         }
         return res;
    }

28. 找出字符串中第一个匹配项的下标 

要用kmp。麻烦,

暴力解法:

  int strStr(string haystack, string needle) {

        if(haystack.size()<needle.size()){
            return -1;
        }
        int index=INT_MAX;
        int k=0;
        for(int i=0;i<haystack.size();++i)
        {
            for(int j=i;j<haystack.size();++j)
            {
                if(haystack[j]==needle[k])
                {
                    k++;
                    if(k==needle.size())
                    {
                       index=i;
                       return i;
                    }
                }
                else{
                    k=0;
                    break;
                }

            }
        }
        return -1;
    }

kmp:  面试的时候要是面试官让你去写kmp,就把屎盆子扣他脑门,,看着代码感觉不多,思想是极其巧妙的,很难理解,而且稍微一变形,你会难的你根本不知道用kmp从何下手,Knuth-Morris-Pratt 三兄弟,花了若干年研究的成果,在网上各路大神眼里,居然是个简单算法。。。

总之除非你把kmp理解的非常非常清楚,随便一个类型题就就能在15分钟内靠理解的kmp搞出来,那你可以去申请图灵奖了

反正我是每次写到这题就是暴力,然后看看kmp题解,看懂一次 过几天就忘了文章来源地址https://www.toymoban.com/news/detail-480986.html

    void ex(int *arr,const string&needle)
    {
        int j=0;
        arr[0]=j;
        for(int i=1;i<needle.size();++i)
        {
            while(j>0&&needle[j]!=needle[i])
            {
                j=arr[j-1];
            }
            if(needle[i]==needle[j])
            {
                j++;
            }
            arr[i]=j;
        }
    }
    int strStr(string haystack, string needle) {
        if(needle.size()==0)
        {
            return -1;
        }
        int arr[needle.size()];
        ex(arr,needle);
        int j=0;
        for(int i=0;i<haystack.size();++i)
        {
            while(j>0&&haystack[i]!=needle[j]) //回退
            {
                j=arr[j-1];
            }
            if(haystack[i]==needle[j])
            {
                j++;
            }
            if(j==needle.size())
            {
                return i-needle.size()+1;
            }
        }
        return -1;
    }

到了这里,关于面试经典150题:数组/字符串合集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【面试经典150 | 数组】合并两个有序数组

    本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删: Tag:介绍本题牵涉到的知识点、数据结构; 题目来源:

    2024年02月09日
    浏览(45)
  • 【面试经典150 | 数组】移除元素

    本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删: Tag:介绍本题牵涉到的知识点、数据结构; 题目来源:

    2024年02月09日
    浏览(77)
  • 1.5 面试经典150题 - 轮转数组

    轮转数组 给定一个整数数组  nums ,将数组中的元素向右轮转  k   个位置,其中  k   是非负数。 注意:本题需要原地操作 本题解题思路是: 以[]1, 2, 3, 4, 5, 6, 7] 3 为例 1. 先整体轮转,将 [1, 2, 3, 4, 5, 6, 7]转为 [7, 6, 5, 4, 3, 2, 1] 2. 再局部分别轮转前k个和剩余的,[5, 6, 7,   

    2024年01月16日
    浏览(37)
  • 【面试经典 150 | 数组】最后一个单词的长度

    本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删: Tag:介绍本题牵涉到的知识点、数据结构; 题目来源:

    2024年04月22日
    浏览(59)
  • 手撕前端面试题【javascript~ 总成绩排名、子字符串频次统计、继承、判断斐波那契数组等】

    html页面的骨架,相当于人的骨头,只有骨头是不是看着有点瘆人,只有HTML也是如此。 css,相当于把骨架修饰起来,相当于人的皮肉。 js(javascripts),动起来,相当于人的血液,大脑等一切能使人动起来的器官或者其他的。 在刷题之前先介绍一下牛客。Leetcode有的刷题牛客都有,

    2024年01月15日
    浏览(45)
  • 1.1 面试经典 150 题-合并两个有序数组

    合并两个有序数组

    2024年01月16日
    浏览(50)
  • LeetCode150道面试经典题-合并两个有序数组(简单)

    题目: 给你两个按 非递减顺序 排列的整数数组  nums1 和 nums2 ,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 注意: 最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对

    2024年02月14日
    浏览(44)
  • leetcode每日一题——189.轮转数组(面试经典150题)

    189. 轮转数组 - 力扣(LeetCode) 给定一个整数数组  nums ,将数组中的元素 向右轮转  k   个位置 ,其中  k   是非负数。 示例1: 示例2: 1 = nums.length = 105 -231 = nums[i] = 231 - 1 0 = k = 105        对题目进行分析可知,我们需要根据轮转量k,将数组后面的k个元素按照原来的顺

    2024年02月12日
    浏览(39)
  • 面试经典150题——删除有序数组中的重复项

    题目来源 力扣每日一题;题序:26 我的题解 方法一 双指针 使用两个指针分别指向相同元素的左右边界,再利用一个count记录最终需要的数组长度。 时间复杂度 :O(n) 空间复杂度 :O(1) 有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持

    2024年04月14日
    浏览(60)
  • mysql 解析json字符串、数组字符串、json数组字符串

    笔者使用mysql 5.7进行了一次json字符串的解析,因为一直在搞大数据相关的数据库、olap等,太久没有用mysql5.x的版本,一些函数已经不知道支不支持,我的同事建议我使用like、rlike模糊匹配的方式,身为数据人我不太喜欢用这种手段,因为他们比较低效。于是我想这里总结一下

    2024年02月16日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包