Leetcode---字符串和数组【总结】

字符串和数组---总结

本博客的题均为leetcode上的摘录,都是我的刷题答案,仅做参考,若有错误,欢迎指正

直接上题目:

一、旋转数组

给定一个数组,将数组中的元素向右移动 个位置,其中 是非负数。

示例 1:

输入: [1,2,3,4,5,6,7]k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入: [-1,-100,3,99]k = 2
输出: [3,99,-1,-100]
解释: 
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

说明:

  • 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
  • 要求使用空间复杂度为 O(1) 的 原地 算法。
//C++实现
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        //方法一
        //时间复杂度仅为O(n+k)
        if(nums.size()<2)
            return ;
        if(k>nums.size())       //如果k大于nums的长度,只需求余数即可
            k=k%nums.size();
        //k=k%nums.size();      //可以不用判断,全部求余即可
        
        stack<int> s;
        for(int i=0;i<k;i++)
            s.push(nums[nums.size()-1-i]);
        for(int i=nums.size()-1;i>=k;i--)
                nums[i]=nums[i-k];
        for(int i=0;i<k;i++)
        {
            nums[i]=s.top();
            s.pop();
        }
        //方法二    
        //还可以使用三个reverse()进行操作,很巧的方法
        /*
        *方法三
        *此方法会超时,时间复杂度太大了
        int i=0;
        while(i<k)
        {
            int temp;
            temp=*(nums.end()-1);
            //temp=nums.top();
            
            for(int i=nums.size()-1;i>0;i--)
                nums[i]=nums[i-1];
            nums[0]=temp;
            i++;
        }
        */
    }
};

二、杨辉三角 II

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

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

示例:

输入: 3
输出: [1,3,3,1]

进阶:

你可以优化你的算法到 O(k) 空间复杂度吗?

//C++实现
class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<vector<int>> ret(rowIndex+1);   //输入的数,即为杨辉三角的行数
        
        for(int i=0;i<ret.size();i++)
        {
            ret[i].resize(i+1);     //杨辉三角每一行的列数即为行数的值,第一行为一列,第二行为两列。。。
            
            for(int j=0;j<i+1;j++)
            {
                if(j==0 || j==i)        //每行的第一个和最后一个元素为1
                    ret[i][j]=1;
                else                    //其他元素为上一行的同一列和前一列的元素和
                {
                    ret[i][j]=ret[i-1][j-1]+ret[i-1][j];
                }
            }
        }
        return ret[rowIndex];
    }
};

三、翻转字符串里的单词

给定一个字符串,逐个翻转字符串中的每个单词。

示例 1:

输入: "the sky is blue"
输出: "blue is sky the"

示例 2:

输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例 3:

输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

说明:

  • 无空格字符构成一个单词。
  • 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
  • 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
//C++实现
class Solution {
public:
    string reverseWords(string s) {
        //find_first_not_of(" "):找到第一个不是“ ”的字符,返回index
        //find_first_of(" "):找到第一个“ ”字符,返回index
        //substr()函数
        //如果字符串为空,返回s
        if(s.empty())      
            return s;
        //处理字符串前后的空格
        s.erase(0,s.find_first_not_of(" "));      //去除字符串前面所有的空格
        //s.erase(s.find_last_not_of(" ")+1);     //此语句是删除字符串末尾的所有空格
        s+=" ";     //保持字符串末尾至少有一个空格,作为循环判断条件
        
        vector<string> ret;     //定义一个vector存储分离出的字符串单词
        while(!s.empty())       //以s非空作为循环条件
        {
            size_t index=s.find_first_of(" ");  //获取第一个“ ”的索引,下面用substr截取第一个单词
            ret.push_back(s.substr(0,index));   //根据第一个空格的位置,截取第一个单词,放入ret当中
            s.erase(0,index);                   //提取出第一个单词之后,将他从s字符串删除
            
            s.erase(0,s.find_first_not_of(" "));//每提取出一个单词之后,将字符串前面空格清空,方便下一次循环操作
        }
        
        //循环将ret存储的单词逐个加空格,倒序返回
        s=s+*(ret.end()-1);     
        for(int i=ret.size()-2;i>=0;i--)
            s=s+" "+ret[i];
        return s;
    }
};

这个题目让我很好的理解和使用C++里面的字符快速查找函数,在进行字符串的操作过程中使用很方便,这里主要是四个函数:

find_first_of(string &str):找到字符串中的第一个str字符

find_first_not_of(string &str):找到字符串中的第一个不是str的字符

find_last_of(string &str):找到字符串中最后一个str字符

find_last_not_of(string &str):找到字符串中最后一个非str字符

除此之外还有字符串的截取函数:substr(),能够根据索引截取出字符串中的指定片段,再结合string的erase()函数,就能够很自如的对字符串进行剪切,截取以及删减。

四、反转字符串中的单词 III

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

示例 1:

输入: "Let's take LeetCode contest"
输出: "s'teL ekat edoCteeL tsetnoc" 

注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

//C++实现
class Solution {
public:
    string reverseWords(string s) {
        
        //s.erase(0,s.find_first_not_of(" "));
        //s.erase(s.find_last_not_of(" "));
        if(s.empty())      //处理字符串为空情况
            return s;
        vector<string> ret;
        while(!s.empty())
        {
            size_t index=s.find_first_of(" ");  //获取第一个空格的index
            if(index==string::npos)     //如果检索不到空格,返回string::npos,表示到达最后一个单词,直接反转后存入即可
            {
                reverse(s.begin(),s.end());
                ret.push_back(s);
                break;
            }
            string t = s.substr(0,index);   //提取单词
            reverse(t.begin(),t.end());     //反转单词
            ret.push_back(t);               //存储单词
            s.erase(0,index);               //将单词从字符串删除
            s.erase(0,s.find_first_not_of(" "));        //清除字符串前面的空格
        }
        s.clear();      //清空字符串
        s+=ret[0];
        for(int i=1;i<ret.size();i++)
        {
            s=s+" "+ret[i];
        }
        return s;
    }
};

五、删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

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

示例 1:

给定数组 nums = [1,1,2], 
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 
你不需要考虑数组中超出新长度后面的元素。

示例 2:

给定 nums = [0,0,1,1,1,2,2,3,3,4],

函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0,1,2,3,4。
你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}
//C++实现
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        
        //题目隐含条件:排序数组,都已经排好序了
        //双指针的做法,很巧
        /*
        if(nums.size()<2)        //vector为空或者只有一个元素的都可以忽略,直接返回size()即可
            return nums.size();
        
        int i=0,j=1;        //定义两个索引值,表示两个指针,分别进行操作
        while(j<nums.size())
        {
            if(nums[i]==nums[j])    //如果碰到连续相等的字符,j++,j往后移动,直到不是相等的数
                j++;
            else    //如果前后不相等,直接跳过,并且将j指向的那个元素移到i+1处,即将不相等的数连续的放在一起
            {
                i++;
                nums[i]=nums[j];
                j++;
            }
            
        }
        return i+1;        //最后不重复的数只是i+1,后面的都是重复后剩下的数
        */
        

        //初次做法:时间超时
        if(nums.size()<2)
            return nums.size();
        
        int count=0;
        for(int i=0;i<nums.size()-1;i++)
        {
            int temp=i+1;
            while(temp<nums.size()-1 && nums[temp] == nums[i])
            {
                temp++;
                count++;
            }
            if(temp==i+1)
                break;
            else
            {
                int len=temp;
                for(int j=i+1;j<len;j++,temp++)
                    nums[j]=nums[temp];
            }
            
        }
        return nums.size()-count;
        
    }
};

此题的双指针解法充分体现了双指针的内涵,值得学习和深究。

六、移动零

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

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

说明:

  1. 必须在原数组上操作,不能拷贝额外的数组。
  2. 尽量减少操作次数。
//C++实现
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        /*冒泡法*/
        
        for(int i=0;i<nums.size()-1;i++)
        {
            for(int j=0;j<nums.size()-i-1;j++)
            {
                if(nums[j]==0)
                {
                    int temp=nums[j];
                    nums[j]=nums[j+1];
                    nums[j+1]=temp;
                }
                
            }
        }
        
        
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值