对撞指针思想解LeetCode 167&125&344&345&11&15

167 

思想:找到的两个数一定是一左一右的。

Nums[i]+nums[j]<target:i++

Nums[i]+nums[j]>target:j--

直到nums[i]+nums[j]=target

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
    	//对撞指针思想 因为是有序数组,在数组两侧分别找一个结果 
		int l=0, r=numbers.size()-1;
		while(l<r){
			if(numbers[l] + numbers[r] == target)
			{
				int res[2]={l+1,r+1};
				return vector<int>(res,res+2);
			}else if(numbers[l] + numbers[r] > target)
				r--;
			else
				l++; 
		}
		return vector<int>(); 
    }
};

125

/**
	给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
	输入: "A man, a plan, a canal: Panama"
	输出: true
	输入: "race a car"
	输出: false
*/ 

class Solution {
public:
    bool isPalindrome(string s) {
    	//空字符串
		if(s.size()==0) return true; 
		
		//使用双指针对撞思想,一个指针从头开始遍历,一个指针从尾开始,看有效字符是否相同
		int r=0, l=s.size()-1;
	
		while(r<l)
		{
			if(isalnum(s[r])==0) r++; //找到符合要求的字符 
			else if(isalnum(s[l])==0) l--; //找到符合要求的字符 
			else
			{
				if(toupper(s[r]) == toupper(s[l]))
				{
					l--;
					r++;
				}else
					return false;
			} 
			
		} 
		return true;
    }
};

344

/**
	编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
	不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
	输入:["h","e","l","l","o"]
	输出:["o","l","l","e","h"]
*/ 

class Solution {
public:
    void reverseString(vector<char>& s) {
		//对撞指针,对换位置
		int l=0,r=s.size()-1;
		while(l<r)
		{
			swap(s[r],s[l]);
			l++;
			r--;
		} 
    }
};

345

/**
	编写一个函数,以字符串作为输入,反转该字符串中的元音字母。
	输入: "hello"
	输出: "holle"
*/ 

class Solution {
public:
    string reverseVowels(string s) {
    	//双指针思想 找到左右两个元音,交换位置 
    	int l=0,r=s.size()-1;
		while(l<r)
		{
			if(is_ok(s[l])==0) l++;
			else if(is_ok(s[r])==0) r--;
			else
			{
				swap(s[l],s[r]);
				l++;
				r--;
			}	
		} 
		return s;

    }
    bool is_ok(char ch){
	    if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u'||
            ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U')
		    return true;
	    return false;
    }
};

11

思想:

/**
	给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点(i,ai) 。
	在坐标内画 n 条垂直线,垂直线 i的两个端点分别为(i,ai) 和 (i, 0)。
	找出其中的两条线,使得它们与x轴共同构成的容器可以容纳最多的水。
	输入:[1,8,6,2,5,4,8,3,7]
	输出:49
*/ 

class Solution {
public:
    int maxArea(vector<int>& height) {
    	//双指针思想 向内移动短板 短板可能变大 S可能变大
		int l=0,r=height.size()-1;
		int ret = min(height[r],height[l])*(r-l); //计算初始面积 
		while(l<r)
		{
			if(height[l]>height[r]) //右边板短 
			{
				r--;
			}else{ //左边板短 
				l++;
			} 
			int area = min(height[l],height[r])*(r-l);
			if(area > ret)
				ret =area;
			
		}
		return ret;
    }
   
    int min(int x,int y)
    {
    	if(x<y)
    		return x;
    	else
    		return y;
    }
};

15

#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
/**
	给你一个包含 n 个整数的数组nums,判断nums中是否存在三个元素 a,b,c ,
	使得a + b + c = 0请你找出所有满足条件且不重复的三元组。
	给定数组 nums = [-1, 0, 1, 2, -1, -4],

	满足要求的三元组集合为:
	[
  		[-1, 0, 1],
  		[-1, -1, 2]
	]

*/ 
class Solution {
public:
    vector< vector<int> > threeSum(vector<int>& nums) {
    	//排序,固定一个数,用对撞指针 
    	vector< vector<int> > res;
    	sort(nums.begin(),nums.end());//排序 
    	int l=0;
		int r=nums.size()-1;
        for(int i=0; i<nums.size(); i++)
        {
        	int target= 0-nums[i];//减掉第一个数字后的目标 
        	
        	//在数组的后端寻找答案
			l=i+1;
			r=nums.size()-1;
			while(l<r)
			{
				if(nums[l]+nums[r]>target)	
					r--;
				else if(nums[l]+nums[r]<target)
					l++;
				else //找到符合条件的 
				{
					int restmp[3]={nums[i],nums[l],nums[r]};
					vector<int> vec(restmp,restmp+3);
					res.push_back(vec);
					//去重[-2,0,0,2,2]
					while(l+1<r && nums[l]==nums[l+1]) // 左边的下一个数字如果和现在的重复,则跳过 
						l++;
					while(l<r-1 && nums[r]==nums[r-1]) // 右边的下一个数字如果和现在的重复,则跳过 
						r--;
					l++;
					r--; 
				}
			} 
			//去重 当以一个数开头用过后,后面以这个数字开头的就是重复的 全部跳过
			while(i+1<nums.size()&&nums[i]==nums[i+1])
				i++;
        }
        
        return res;
    }
};
发布了86 篇原创文章 · 获赞 0 · 访问量 4078

猜你喜欢

转载自blog.csdn.net/qq_31965925/article/details/105327354
今日推荐