leetcode刷题(Java)-双指针

双指针问题

反转字符串

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

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

示例 1:

输入:s = [“h”,“e”,“l”,“l”,“o”] 输出:[“o”,“l”,“l”,“e”,“h”] 示例 2:

输入:s = [“H”,“a”,“n”,“n”,“a”,“h”] 输出:[“h”,“a”,“n”,“n”,“a”,“H”]

class Solution {
    public void reverseString(char[] s) {
        for (int i = 0, j = s.length - 1; i < j; i++, j--) {
            char temp = s[i];
            temp = s[i];
            s[i] = s[j];
            s[j] = temp;
        }
    }
}

283. 移动零

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

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2:

输入: nums = [0] 输出: [0]

class Solution {
	public void moveZeroes(int[] nums) {
		if(nums==null) {
			return;
		}
		//第一次遍历的时候,j指针记录非0的个数,只要是非0的统统都赋给nums[j]
		int j = 0;
		for(int i=0;i<nums.length;++i) {
			if(nums[i]!=0) {
				nums[j++] = nums[i];
			}
		}
		//非0元素统计完了,剩下的都是0了
		//所以第二次遍历把末尾的元素都赋为0即可
		for(int i=j;i<nums.length;++i) {
			nums[i] = 0;
		}
	}
}

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。
输入:[1,8,6,2,5,4,8,3,7]
输出:49 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为
49。 示例 2:

输入:height = [1,1] 输出:1

class Solution {
    public int maxArea(int[] height) {
        int maxS = 0;
        int left = 0;
        int right = height.length - 1;
        while(left<right){
            int curentS =Math.min(height[left],height[right])*(right-left);
            maxS = Math.max(maxS,curentS);
            if(height[left]<height[right]){
                left++;
            }else {
                right--;
            }
        }
        return maxS;
    }
}

LCR 006. 两数之和 II - 输入有序数组

给定一个已按照 升序排列 的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 0 开始计数 ,所以答案数组应当满足
0 <=answer[0] < answer[1] < numbers.length 。

假设数组中存在且只存在一对符合条件的数字,同时一个数字不能使用两次。

示例 1:

输入:numbers = [1,2,4,6,10], target = 8 输出:[1,3]
解释:2 与 6 之和等于目标数 8 。因此
index1 = 1, index2 = 3 。
示例 2:

输入:numbers = [2,3,4], target = 6 输出:[0,2]
示例 3:

输入:numbers = [-1,0], target = -1 输出:[0,1]

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int i = 0;
        int j = numbers.length - 1;
        while (i < j) {
            if (numbers[i] + numbers[j] == target) {
                return new int[]{i,j};
            }else if(numbers[i] + numbers[j]<target){
                i++;
            }else {
                j--;
            }
        }
        return new int[0];
    }
}

15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k
且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释: nums[0] +nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0
示例 3:

输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        // 排序
        Arrays.sort(nums);
        // 新建返回数组
        List<List<Integer>> result = new ArrayList<>();
        // 循环(双指针)
        for (int i = 0; i < nums.length; i++) {
            // 判断
            if (nums[i] > 0) {
                return result;
            }
            // 去重
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            // 定义左右指针
            int left = i + 1;
            int right = nums.length - 1;
            // while
            while (right > left) {
                int sum = nums[i] + nums[left] + nums[right];
                // judge
                if (sum > 0) {
                    right--;
                } else if (sum < 0) {
                    left++;
                } else {
                    // Arrays.asList数组转换成List
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    // 去重
                    while (right > left && nums[right] == nums[right - 1]) right--;
                    while (right > left && nums[left] == nums[left + 1]) left++;
                    // 有了一组=0的之后如果只要right--,和值会变<0,如果只要left++和值会>0,所以需要同时移动
                    right--;
                    left++;
                }
            }
        }
        return result;
    }
}

LCR 181. 字符串中的单词反转

你在与一位习惯从右往左阅读的朋友发消息,他发出的文字顺序都与正常相反但单词内容正确,为了和他顺利交流你决定写一个转换程序,把他所发的消息
message 转换为正常语序。

注意:输入字符串 message
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入: message = “the sky is blue” 输出: “blue is sky the”
示例 2:

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

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

// 双指针
class Solution {
    public String reverseMessage(String message) {
        // 删除首尾空格
        message = message.trim();
        // 双指针i j
        int i = message.length() - 1;
        int j = message.length() - 1;
        // 新建返回值SB res
        StringBuilder res = new StringBuilder();
        // while
        while (i >= 0) {
            while (i >= 0 && message.charAt(i) != ' ') {
                i--;
            }
            res.append(message.substring(i + 1, j + 1)+" ");
            while (i >= 0 && message.charAt(i) == ' ') {
                i--;
            }
            j = i;
        }
        return res.toString().trim();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值