LeetCode(C++):数组和字符串小结(1)

一、旋转数组

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

示例 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) 的原地算法。

第一次代码:没有实现原地算法!时间复杂度过大

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int len=nums.size();
        if(nums.empty()||k%len==0) return;
        if(k>len) k=k%len;
        vector<int> str;
        while(k>0)
        {
            if(k>len) num=k%len;
            for(int i=0;i<num;i++)
            {
                str[i]==nums[len-num];
                num--;
            }
            for(int i=k;i<len-k;i++)
            {
                str[i]==nums[j];
                j++;
                k--;
            }
        }   
    }
};

第二次代码:

思路:

1.排除特殊情况:当nums==0或者k%len==0(不用旋转)

2.当k>len,不需要重复旋转,只需要旋转k%len次;

此处需用到倒置函数reverse()函数:可以对字符串进行反转操作,头文件是#include<algorithm>

容器类型的要用begin()和end()来指定反转的区域,数组类型的直接用int类型即可

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int len=nums.size();
        if(nums.empty()||k%len==0) return;//特殊情况直接排除
        if(k>len) k=k%len;
        
        reverse(nums.begin(),nums.begin()+len-k);
        reverse(nums.begin()+len-k,nums.end());
        reverse(nums.begin(),nums.end());
    }
};

第三次代码:

思路:利用STL的push_back()、erase()函数每次从数组的开头取出数字插入到nums的末尾,再将开头擦去;

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int len=nums.size();
        if(nums.empty()||k%len==0) return;
        if(k>len) k=k%len;
        
        for(int i=0;i<len-k;i++)
        {
            nums.push_back(nums[0]);
            nums.erase(nums.begin());
        }
    }
};

二、杨辉三角 II

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

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

示例:

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

进阶:

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

思路:

1.和之前的杨辉三角I一样,把所有的计算出来,然后输出第n行,但效率不高;

2.利用两个for循环,除了第一个数为1,后面的数都是上一次循环的数值加上他前面位置的数值之和,不停的更新每一个位置的值,便可以得到第n行,效率较高。

例如:

rowIndex=4 ,输出结果应为 1  4  6  4  1

当i=1,res =  1   ,1

当i=2,res =  1    ,2 ,1

当i=3,res =  1   , 3, 3,1

当i=4,res =  1 , 4,   6,  4,  1

代码:

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> res(rowIndex + 1);//需要开辟n+1个大小,因为第n行有n+1个数字
        res[0] = 1;
        for(int i = 1; i <= rowIndex; ++i){//i必须<=rowIndex,i控制总体循环次数
            for(int j = i ;j >= 1;--j){//j控制累加循环,从倒数第一个数每次计算完--,直到正向的第二个数(第一个1不需要计算)
                res[j] += res[j-1];
            }
        }
        return res;
    }
};

注:

 1.需要开辟n+1个大小,因为第n行有n+1个数字;

 2.i必须<=rowIndex,i控制总体循环次数;

 3.j控制累加循环,从倒数第一个数每次计算完--,直到正向的第二个数(第一个1不需要计算)

 

三、翻转字符串里的单词

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

 

示例 1:

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

示例 2:

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

示例 3:

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

 

说明:

  • 无空格字符构成一个单词。
  • 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
  • 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

 

进阶:

请选用 C 语言的用户尝试使用 O(1) 额外空间复杂度的原地解法。

 

思路:

1.传统方法:先整体翻转一次,然后再翻转每个单词;

2.利用栈先进后出的特点,从头遍历,每次遇到一个空格,则空格前的字符是一个单词,将单词存入到栈里面,全部压入栈后,每次将栈顶出栈,如果栈中还有单词,则将栈顶后连接一个空格,如果是最后一个单词的时候,不需要加空格,直接连接到末尾就可以。

注:这个方法直接不需要考虑源字符串中空格的个数,以及翻转后收尾是否有多余空格

代码:(思路2)

class Solution {
public:
    string reverseWords(string s) {
        stack<string> st;
		string t,ans;
		for (int i = 0; i < s.size(); ++i){//将每一个单词压栈
			if (s[i] != ' '){
				while (s[i] != ' ' && i < s.size()){
					t += s[i];
					++i;
				}
				st.push(t);
				t.clear();
			}
		}
		while (!st.empty()){
			string tmp = st.top();
			st.pop();
			if (tmp != " "){
				if (st.empty())//判断是否为栈中的最后一个单词
					ans += tmp;
				else
					ans += tmp + ' ';
			}
		}
		return ans;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值