LeetCode之 Longest Palindromic Substring、Container With Most Water、3Sum

本文深入探讨了最长回文子串、容器盛水问题及三数之和的算法解决方案,通过实例详细解析了各种算法的实现思路与复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Longest Palindromic Substring最大回文子串

考察字符串,分回文子串长度为奇数和回文子串长度为偶数两种情况考虑

#include <iostream>
using namespace std;

/**思路:
* 从回文串的对称点开始,依次向左向右比较,不相同的时候停止遍历,不断更新,直到找出最大的长度的回文子串。
*    (1)回文子串长度为奇数:对称点只有一个字符
*    (2)回文子串长度为偶数:对称点有两个字符
* 时间复杂度为O(n^2):对称点的数量为O(n),每次查找的时间也为O(n),所有总时间复杂度为O(n^2) 
*/

class Solution {
public:
    string longestPalindrome(string s) {
        int len=s.length(); //字符串的长度
		int i,left,right;  //i是当前对称点
		if(len==0)
			return s;
		string result="";
		for(i=0;i<len;i++) //回文子串长度为奇数
		{
            left=right=i;
            while(left>0 && right<len-1 && s[left-1]==s[right+1]) //对称,向左右移动
            {
                left--;
                right++;
            }
            if(result.length()<right-left+1) //不断更新
                result=s.substr(left,right-left+1);
		}
        for(i=0;i<len;i++)
        {//回文子串长度为偶数
            if(s[i]==s[i+1]){  //中心相等
                left=i;
                right=i+1;
                while(left>0 && right<len-1 && s[left-1]==s[right+1]){ //对称,向左右移动
                    left--;
                    right++;
                }
                if(result.length()<right-left+1) //不断更新
                    result=s.substr(left,right-left+1);
            }
        }
		return result;
    }
};

int main()
{
	string s="ccc";
	Solution ss;
	cout<<ss.longestPalindrome(s);
	return 0;
}

Container With Most Water

#include <iostream>
#include <vector>
using namespace std;

/**思路:
  * 从两边往中间找,每次放弃最短的板。
  *从起点和终点开始找,宽度最大,这时每移动一次其中一个点,必然宽度变小。
  *最大面积,只有高度增大才有可能做到,即放弃高度较小的点。
*/

class Solution {
public:
    int maxArea(vector<int> &height) {
        int area=0,h=0;
		int i=1,j=height.size();
		while(i!=j)
		{
			//min(height[i-1],height[j-1]):装多少水是由最短的板决定的
			area=max(area,(j-i)*min(height[i-1],height[j-1]));  
			height[i-1]>height[j-1]?j--:i++;
			
		}
		return area;
    }
};

int main()
{
	vector<int> height={4,2,4,1,7,3,2};
	Solution ss;
	int area;
	area=ss.maxArea(height);
	cout<<area;
	return 0;
}

3Sum

类比Two Sum
注:首先要注意排除重复;另外要注意排除重复时left和right的位置已经改变,所以使用res里的值

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

/**
 * (1)首先用sort函数对数组进行排序(从小到大)
 * (2)依次取出第 i 个数(i从0开始),并且不重复的选取(跳过重复的数)
 * (3)这样问题就转换为 2 个数求和的问题(可以用双指针解决方法)
 *  2 数求和问题
 *     (4)定义两个指针:左指针(left) 和 右指针(right)
 *     (5)找出固定 left, 此时left所指的位置为数组中最小数,再找到两个数和 不大于 target 的最大 right 的位置
 *     (6)调整 left 的位置(后移),求解和是否为 target O(n)
 *     (7)时间复杂度:O(nlogn) + O(n)
*/

class Solution {
public:
	vector<vector<int>> threeSum(vector<int> &num) {
        sort(num.begin(),num.end());//从小到大排序
		vector<vector<int>> result; //存放返回结果
		int left=0,right=0;
		
		if(num.size()<3) return result;
		
		for(int i=0;i<num.size();i++)
		{
			if(i!=0&&num[i]==num[i-1]) //防止重复
			   continue;
			left=i+1;
			right=num.size()-1;
			while(left<right)
			{	
				if(num[i]+num[left]+num[right]==0)
				{
					vector<int> res;
					res.push_back(num[i]);
					res.push_back(num[left]);
					res.push_back(num[right]);
					result.push_back(res);
					left++;
					right--;
					//排除重复,用res,因为此时left和right都被改变了
                    //[-2,0,1,1,2]对应输出应该为:[[-2,0,2],[-2,1,1]]
					while(left<right && num[left]==res[1]) left++;
				    while(left<right && num[right]==res[2]) right--;
				}else if(num[i]+num[left]+num[right]>0){
					right--; //排序了的数组,right--减小3sum
				}else{
					left++; //增大3sum
				}
			}
		}
        return result;
    }
};

int main()
{
	vector<int> s={-2,0,1,1,2};
	Solution ss;
	vector<vector<int>> result;
	result=ss.threeSum(s);
	for(int i=0;i<result.size();i++)
	{
		for(int k=0;k<result[i].size();k++)
			cout<<result[i][k]<<",";
		cout<<"\n";
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值