leetcode 数组和字符串

寻找数组的中心索引

给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。
我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。

//c++
class Solution {
public:
    int pivotIndex(vector<int>& nums) {
    
    auto begin = nums.begin();
	auto end = nums.end();
	int cnt = 0;
	int subsum = 0;
	int sum = 0;
	if (begin != end)
	{
		//第一次遍历先求和
		for (auto p = begin; p != end; p++)
		{
			sum = *p + sum;
		}
		//第二次遍历找中心索引(通过索引两边的和一样来判断)
		for (auto p = begin; p != end; p++)
		{
			subsum = *p + subsum;
			cnt++;
			if ((sum - subsum + *p)==subsum)
			{
				return cnt-1;
			}
            
		}
        return -1;
	}
    else
        return -1;
    }
};
至少是其他数字两倍的最大数

在一个给定的数组nums中,总是存在一个最大元素 。
查找数组中的最大元素是否至少是数组中每个其他数字的两倍。
如果是,则返回最大元素的索引,否则返回-1。

class Solution {
public:
    int dominantIndex(vector<int>& nums) {
    int index_max = -1;
	int flag = 0;
	int max = 0;
	
	//先找最大值和最值对应的索引
	for (auto i = 0; i < nums.size(); i++)
	{
		if (nums[i] > max)
		{
			max = nums[i];
			index_max = i;
		}
	}
	//遍历数组
	for (auto i = 0; i < nums.size() ; i++)
	{
		if (i == index_max)
		{
			continue;
		}
		if (2 * nums[i] > max)
		{
			flag = 1;
		}
	}
	if (flag == 1)
	{
		return -1;
	}
	else
	{
		return index_max;
	}
        
    }
};
加一

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。

class Solution {
public:
    vector<int> plusOne(vector<int>& digits) {
	
    auto begin = digits.begin();
	auto end = digits.end();
	int flag=0; //进位标记
	*(end - 1)=*(end - 1)+1; //最后一位+1
	
	
	for (auto p = end-1; p != begin; p--)
	{
		if (flag==0 && *p == 10)
		{
			*p = 0;
			flag = 1;
		}
		else if(flag==1)
		{
			(*p)++;
			if (*p == 10)
			{	
				*p = 0;
				flag = 1;
			}
			else
			{
				flag = 0;
			}
		}
	}
	if (flag == 1)
	{
		*begin = *begin + 1;	
	}
	//遍历到最后,如果第一位是10的情况下,使其变为[1,0]
	if (*begin == 10)
	{
		*begin = 0;
		digits.insert(begin, 1);
	}
    return digits;
    }
};
对角线遍历

给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
在这里插入图片描述
解题关键在于:
1.每一趟的坐标(x,y),x+y总是相等的,且随着每一趟加1
2.每一趟的x,y的取值范围需要考虑,不能超过矩阵的边界

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
    vector<int> result;
    //空容器直接返回结果
    if(matrix.size() == 0)
    {
        return result;
    }
    if((matrix[0].size()==0))
    {
        return result;
    }
    
    int row = matrix.size()-1;
	int column = (*(matrix.begin())).size()-1;
	int i = 0, j = 0;
	int sum = row + column;
	int temp = 0;//循环每一趟的条件
	int flag = 0;//作为每一趟正反向的标致,和边界条件
  
	while (temp <= sum)
	{
		if (flag % 2 == 0) //正向
		{
			i = flag;     //边界条件的设置
			if (i > row)   //正向,i都在递减,j都在递增
			{
				i = row;
			}
			j = temp - i;
			if (j<0)
			{
				j = 0;
			}
			while (i >= 0 && j <= column)
			{
				result.push_back(matrix[i][j]);
				i--;
				j++;
			}
			flag++;
		}
		else if (flag % 2 == 1)  //反向
		{
			j = flag;
			if (j > column)
			{
				j = column;
			}
			i = temp-j;
			if (i< 0)
			{
				i = 0;
			}
			while (i <= row && j >= 0)
			{
				result.push_back(matrix[i][j]);
				i++;
				j--;
			}
			flag++;
		}
		
		temp++;
	}
    return result;
    }
};
螺旋矩阵

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
解题思路:按层遍历(分上,右,下,左依次)
在这里插入图片描述

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
    vector<int> result;
    if(matrix.size()==0)
    {
        return result;
    }
    if(matrix[0].size()==0)
    {
        return result;
    }
    int row = matrix.size();  //行
	int column = matrix[0].size();  //列
	//右下角坐标必定是(row-1,column-1)
	row = row - 1;
	column = column - 1;
	//左上角坐标必定是(0,0)
	int i = 0, j = 0; //左上角初始坐标
	int x = 0, y = 0; //遍历时的坐标 
        
	while (i < row && j < column)
	{
		//top 
		for (y=j;y <= column; y++)
		{
            result.push_back(matrix[i][y]);
		}
		//right
		for (x=i+1; x <= row; x++)
		{
            result.push_back(matrix[x][column]);
		}
		//bottom
		for (y = column-1; y > j; y--)
		{
            result.push_back(matrix[row][y]);
		}
		//left
		for (x = row; x > i; x--)
		{
            result.push_back(matrix[x][j]);
		}
		//进入里一层
		i++;
		j++;
		row--;
		column--;
	}
	//针对[[2],[3]]等类似的情况
	if ((i <= row && j <= column))
	{	
		for (x = i; x <= row; x++)
		{
			for (y = j; y <= column; y++)
			{
                result.push_back(matrix[x][y]);
			}
		}
	}
    return result; 
    }
};
杨辉三角

给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
    vector<vector<int>> generate;
    if(numRows==0)
    {
        return generate;
    }
    else
    {
        for (int i = 1; i <= numRows; i++)
        {
            vector<int> temp;
            if (i == 1)
            {
                temp.push_back(1);
                generate.push_back(temp);
            }
            else if(i == 2)
            {
                temp.push_back(1);
                temp.push_back(1);
                generate.push_back(temp);
            }
            else   //从第三层开始6
            {
                temp.push_back(1);
                temp.push_back(1);

                for (int x = 0; x < i - 2; x++)  //每一层等于上一层的2值之和
                {
                    auto p = temp.begin();
                    int sum = generate[i - 2][x] + generate[i - 2][x + 1];
                    temp.insert(p+1, sum);				
                }


                generate.push_back(temp);
            }
        }
    }   
     return generate;
    }
};
二进制求和

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0。

class Solution {
public:
    string addBinary(string a, string b) {
    string result;
	int flag = 0; //初始进位标志为0

	//交换a,b,保证a的长度大于等于b
	if (a.length() < b.length())
	{
		result = a;
		a = b;
		b = result;
	}
	//结果保存在多出一位的字符串中,并默认所有字符串位为0
	result.resize(a.length() + 1, '0');
	//将b的前几位补0
	int length = a.length() - b.length();
	if(a.length()>b.length())
	{
		for (int i = 0; i <length; i++)
		{
			auto p = b.begin();
			b.insert(p, '0');
		}
	}
	//执行两数相加
	for (int i = a.length() - 1; i >= 0; i--)
	{
		if (a[i] == '0' && b[i] == '0')
		{
			if (flag == 0)
			{
				result[i + 1] = '0';
				flag = 0;
			}
			else if (flag == 1)
			{
				result[i + 1] = '1';
				flag = 0;
			}
			
		}
		else if ((a[i] == '0' && b[i] == '1') || (a[i] == '1' && b[i] == '0'))
		{
			if (flag == 0)
			{
				result[i + 1] = '1';
				flag = 0;
			}
			else if(flag == 1)
			{
				result[i + 1] = '0';
				flag = 1;
			}
		}
		else if (a[i] == '1' && b[i] == '1')
		{
			if (flag == 0)
			{
				result[i + 1] = '0';
				flag = 1;
			}
			else if(flag == 1)
			{
				result[i + 1] = '1';
				flag = 1;
			}
		}
	}
	//最后如果进位标志为1则置1,为0则删除首位
	if (flag == 1)
	{
		result[0] = '1';
	}
	else
	{
		result.erase(0, 1);
	}

	return result;
    }
};
最长公共前缀

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

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

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
    string result={};
    if(strs.size()==0)
    {
        return result;
    }
	int nums = strs.size();
	int minlen = 0;
	int flag = -1; //标志位记字符串的异同//同时也用来记字符串存在不同时的位置
	
	//得到最短的字符串长度
	minlen = strs[0].size();
	for (int i = 0; i < nums; i++)
	{
		if (strs[i].size() <= minlen)
		{
			minlen = strs[i].size();
		}
	}
	
	//查找最长公共前缀

	for (int i = 0; i < minlen; i++)
	{
		if (flag == -1)
		{
			for (int j = 0; j < nums - 1; j++)
			{
				if (strs[j][i] == strs[j + 1][i])
				{
					flag = -1;
				}
				else
				{
					flag = i;
					break;
				}
			}
		}
		else
		{
			break;
		}
	}
	

	if (flag == 0)  //字符串第一个位置便存在差异,所以直接返回
	{
		return result;
	}
	else if (flag == -1) //字符串按照最短长度遍历完,则最长公共前缀就是最短的那个字符串
	{
		result.append(strs[0], 0, minlen);
        return result;
	}
	else    //其他情况根据不同的字符串位置
	{
		cout << flag << endl;
		result.append(strs[0], 0, flag);
        return result;
	}
	
    }
};
反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

class Solution {
public:
    void reverseString(vector<char>& s) {
    if(s.size()==0)
    {
      s={};  
    }
    else
    {    
        char temp;
        for (auto begin = s.begin(),end = s.end() - 1; begin <= end; begin++, end--)
        {
            temp = *begin;
            *begin = *end;
            *end = temp;
        }
       
    }

    }
};
两数之和 II - 输入有序数组

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
    vector<int> twoSum;  
	int len = numbers.size(); //有序数组的长度

	for (int i = 0; i <= len - 1; i++)
	{
		for (int j = i + 1; j <= len - 1; j++)
		{
           
			if (target - numbers[i] == numbers[j])
			{
				twoSum.push_back(i + 1);
				twoSum.push_back(j + 1);
			}
			//考虑到[0,0,0,.....9,9,9,9,9]等输入情况,设置一个跳出循环
            if (numbers[i] == numbers[i + 1])
			{
				break;
			}

		}
	}
    return twoSum;
    }
};

官方解答有更优质的思路
我们使用两个指针,初始分别位于第一个元素和最后一个元素位置,比较这两个元素之和与目标值的大小。如果和等于目标值,我们发现了这个唯一解。如果比目标值小,我们将较小元素指针增加一。如果比目标值大,我们将较大指针减小一。移动指针后重复上述比较知道找到答案。

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int low = 0, high = numbers.size() - 1;
        while (low < high) {
            int sum = numbers[low] + numbers[high];
            if (sum == target)
                return {low + 1, high + 1};
            else if (sum < target)
                ++low;
            else
                --high;
        }
        return {-1, -1};
    }
};

//作者:LeetCode

移除元素

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

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

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

解题的方式在于快慢指针

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
    int k = 0;  //k为慢指针
    if(nums.size()==0)
    {
        return k;   
    }
    int len = nums.size()-1;
	for (int i = 0; i <=len ; i++)  //i为快指针
	{
		if (nums[i] != val)
		{
			nums[k] = nums[i];
			k++;
		}
	}
	return k;
    }
};
最大连续1的个数

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

class Solution {
public:
    int findMaxConsecutiveOnes(vector<int>& nums) {
        int maxn=0;
        int n=0;
        for(int i=0;i<nums.size();i++)
        {
            if(nums[i]){
                n++;
                maxn=max(n,maxn);
            }
            else n=0;
        }
        return maxn;
    }
};
长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
    
    if(nums.size()==0)
    {
        return 0;
    }
    int len = nums.size()-1;
	int n = 0, sum = 0, minn =99999;

	for (int i = 0; i <= len; i++)
	{
		sum = 0;
		n = 0;
		for (int j = i; j <= len; j++)
		{
			sum = sum + nums[j];
			n++;
			if (sum >= s)
			{
				minn = min(n, minn);
				break;
			}
		}
		
		
	}
    if(minn==99999)
    {
        return 0;
    }
	else
    {
          return minn;     
    }
        
    }
};

官方提供思路,使用双指针
我们用 2 个指针,一个指向数组开始的位置,一个指向数组最后的位置,并维护区间内的和 sum 大于等于 s 同时数组长度最小。

int minSubArrayLen(int s, vector<int>& nums)
{
    int n = nums.size();
    int ans = INT_MAX;
    int left = 0;
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += nums[i];
        while (sum >= s) {
            ans = min(ans, i + 1 - left);  //i+1-left 是当前子数组的长度  
            sum -= nums[left++];  //sum-nums[left]然后增加left  //i是子数组结尾,left是子数组头
        }
    }
    return (ans != INT_MAX) ? ans : 0;
}

//作者:LeetCode

旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
1.解题思路 暴力

2.使用反转

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
	int len=nums.size();
    k=k%len;
    auto start = nums.begin();
	auto end = nums.end();
	
    reverse(start, end);  //第一次反转

	auto start1 = nums.begin();
	for (int i = 1; i <= k; i++)
	{
		start1++;
	}
	start = nums.begin();
	reverse(start, start1);  //前k个元素反转

	start = nums.begin();
	for (int i = 1; i <= k; i++)
	{
		start++;
	}
	end = nums.end();   //后面n-k个元素反转
	reverse(start, end);
    }
        
};

杨辉三角 II

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

class Solution {
public:
    vector<int> getRow(int rowIndex) {
    vector<int> getRow(rowIndex+1);
	getRow[0] = 1;
	for (int i = 1; i <= rowIndex; i++)  //i代表行
	{
		for (int j = i; j >= 1; j--)     //j是每一行的元素位置,从右向左求和赋值
		getRow[j] = getRow[j]+getRow[j - 1];
	}
    return getRow;
    }
};
翻转字符串里的单词

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

class Solution {
public:
    string reverseWords(string s) {
    string res;
    int flag=0;
    if(s.length()==0)
    {
        return s;
    }
    else if(s==" ")
    {
        return "";
    }
	vector<string::iterator> index;  //用于存储每个单词的迭代器位置

	auto start = s.begin();
	auto end = s.end()-1;
	//去除首尾空格
    while(*start == ' ' && start!=end)
	{
		start++;
		if (start == end && *start==' ')
		{

			return "";
			break;
		}
	}
	while (*end== ' ' && start != end)
	{
		end--;
	}
	s.assign(start, end+1);  
	//去除字符串中的多余空格

	for (int i = 0; i <= s.length()-1; i++)
	{
		if (s[i] !=' ' && s[i+1]==' ')
		{
			res.push_back(s[i]);
			res.push_back(' ');
		}
		else if (s[i] == ' ' && s[i + 1] == ' ')
		{
			continue;
		}
		else if(s[i] != ' ')
		{
			res.push_back(s[i]);
		}
	}

	//反转字符串
	reverse(res.begin(), res.end());

	//单个字符串反转
	for (auto p= res.begin();p< res.end();p++)
	{
		if (*p == ' ')
		{
			index.push_back(p);
		}
	}
	if (index.size() == 0)
	{
		reverse(res.begin(), res.end());
	}
	else if (index.size() == 1)
	{
		reverse(res.begin(), index[0]);
		reverse(index[0]+1, res.end());
	}
	else
	{
		reverse(res.begin(), index[0]);
		for (int i = 0; i <= index.size()-2; i++)
		{
			reverse(index[i], index[i+1] + 1);
		}
		reverse(index[index.size()-1]+1, res.end());
	}
    return res;
    }
};

其他的解法参考使用栈

使用stack存储每一个单词
pos指向第一个不是’ '的位置,即单词的首字母
将pos所指的单词保存到stack中
最后将stack中的单词保存到字符串中

class Solution {
public:
    string reverseWords(string s) {
        stack<string> st;
        int pos = 0;

        while (true) {
            pos = s.find_first_not_of(' ', pos);    // 指向单词首字母
            if (pos == string::npos)
                break;
            st.push(s.substr(pos, s.find(' ', pos) - pos));    // 储存单词
            pos = s.find(' ', pos);    // 找到单词后的位置
        }
        string out;
        while (!st.empty()) {
            out += st.top() + " ";
            st.pop();
        }
        out.pop_back();    //删除多余空格
        return out;
    }
};

//作者:da-ge-he-cha

反转字符串中的单词 III

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

class Solution {
public:
    string reverseWords(string s) {
        s.append(" ");
        for(int i = 0, begin = 0, end = 0; i < s.length(); i++) {
            if(s[i] == ' ') {
                end = i - 1;  
                while(begin < end)
                    swap(s[begin++], s[end--]);
                begin = i + 1;
            }
        }
        s.pop_back();
        return s;
    }
};

//作者:yoniga

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值