指针问题解题思路

左右指针

解决问题:数组的相向问题,指针相向移动

引入-- 反转字符串(简单)

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

class Solution {
    public void reverseString(char[] s) {
        int n = s.length;
        int leftPoint = 0;
        int rightPoint = n - 1;
        while (leftPoint < rightPoint) {
            char temp = s[leftPoint];
            s[leftPoint] = s[rightPoint];
            s[rightPoint] = temp;
            ++leftPoint;
            --rightPoint;
        }
    }
}

典型应用-快速排序

在这里插入图片描述
思想:分治法
步骤:
第一步:在待排序的n个记录里,任取一个记录,以该记录的排序码为准,将所有的记录都分为两组,第一组都小于该数,第二组都大于该数
第二步:采用相同的方法,对左、右两组分别进行排序,直到所有记录都排到相应的位置为止。

package com.wang.sort;
 
import java.util.Arrays;
 
/**
 * 快速排序之左右指针<br>
 * 选择最左端的为基准值(pivot)<br>
 * 从右向左遍历,移动hi指针,找到第一个比基准值小的值。<br>
 * 从左向右遍历,移动low指针,找到第一个比基准值大的值。<br>
 * 交换此时low和hi指针位置的数值。循环进行,直到low=hi<br>
 * low等于hi时,把基准值位置与low位置的数值互换。<br>
 * 相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区<br>
 * (partition)操作<br>
 * 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
 * @author wang
 * @Date 2018年4月16日
 *
 */
public class LeftAndRightPointer {
	
	public static void main(String[] args) {
		
		int[] arrays = {12,21,3,5,2,18,7,4,11,9,12};
		System.out.println("快速排序之左右指针排序前:"+Arrays.toString(arrays));
		quickSort(arrays , 0 , arrays.length - 1);
		System.out.println("快速排序之左右指针排序后:"+Arrays.toString(arrays));
		
 
	}
	
	public static void quickSort(int[] arrays,int low,int hi){
		
		if(low < hi){
		
		//求每次分治的分割线
		int divideIndex = getDivideIndex(arrays,low,hi);
		//再递归分别对分割的俩个子数组进行递归排序
		quickSort(arrays,low,divideIndex -1);
		quickSort(arrays,divideIndex + 1, hi);
		
	}
		
	}
	
	public static int getDivideIndex(int[] arrays,int low,int hi){
		//设定arrays[low]为基准值,从右到左移动hi,找到大于第一个大于基准值的数字。
		//从左向右移动low指针,找到第一个小于基准值的数,交换low和high位置上的值
		//直到low=high的时候,将基准值填入arrays[low]
		int baseValue = arrays[low];
		int oldLow = low;
		while(low < hi){
			while (low < hi && arrays[hi] >= baseValue){
				
				hi-- ;
			}
			
			while( low < hi && arrays[low] <= baseValue){
				low++ ;
			}
			if( low < hi){
			swap(arrays,low ,hi);
			}
		}
		
		if(low == hi){
			arrays[oldLow] = arrays[low];
			arrays[low] = baseValue ;
		}
		return low;
	}
	
	public static  void swap( int[] arrays ,int low ,int high){
		int temp = 0;
		temp = arrays[low] ;
		arrays[low] = arrays[high] ;
		arrays[high] = temp;
		
	}
 
}

思考题-三数之和

给你一个包含 n 个整数的数组 nums判断 nums 中是否存在三个元素 a,b,c 使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

前后指针(快慢指针)

解决问题:链表类的问题 (一般情况)

引入-环形引入

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。
在这里插入图片描述
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

public class Solution {
 
	public boolean hasCycle(ListNode head) {
		if (head == null || head.next == null)
			return false;
		ListNode ps = head;
		ListNode pf = head;
		while (pf != null && pf.next != null) {
			ps = ps.next;
			pf = pf.next.next;
			if (ps == pf)
				return true;
		}
		return false;
	}

}

删除有序数组中的重复项

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

class Solution {
    public int removeDuplicates(int[] nums) {
        //使用双指针
        if(nums==null||nums.length==1){
            return nums.length;
        }
        int i=0,j=1;
        while(j<nums.length){
            if(nums[i]==nums[j]){
                j++;
            }else{
                i++;
                nums[i]=nums[j];
                j++;
            }
        }
        return i+1;

    }
}

删除有序数组中的重复项II

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。

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

 public int removeDuplicates2(int[] nums) {
        int i = 0;
        int count = 1;
        for (int j = 1; j < nums.length; j ++){
            if (nums[i] != nums[j]){
                nums[++ i] = nums[j];
                count = 1;
            }else if (count >= 2){
                continue;
            }else{
                nums[++ i] = nums[j];
                count ++;
            }
        }
        return i + 1;
    }

思考题-接雨水

题目描述:给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下
可以接 6 个单位的雨水(蓝色部分表示雨水)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值