双指针问题

目录

leet141.环形链表

leet881.救生艇


leet141.环形链表

链表问题,这里安排两种方案。

由于建议O(1)内存,所以不能对每一个节点是否被遍历过进行储存,于是有了方法一。

方法一:遍历过的节点将内容改为10^{6}(题目中提示说明了 -10^{5}<= Node.val <=10^{5}),只要遍历到10^{6},那么说明成环了。

缺点,会破坏链表内容。实际中可能用不到(如果先复制一遍链表那就消耗了O(n)内存了)。

方法二:双指针,同一个起点,慢指针每次前进1,快指针前进2,速度之差为1,如果产生循环,快指针必然追尾慢指针。

而且限制条件是快指针是否遍历到末端,速度为2,所以循环次数为n/2(假设不成环),速度较快。

要注意的是,当快指针末端恰好成为尾结点时,即p2.next==null时,循环体中的p2.next.next将报错(p2.next为空,那p2.next就没有next这一属性,所以无法访问)

因此,循环条件应该为(p2!=null && p2.next!=null)。

public class L141 {
    public static boolean hasCycle1(ListNode head) {
    	//会摧毁链表
        while(head!=null){
            if(head.val == 1000000){
                return true;
            }
            else{
            head.val = 1000000;
            head = head.next;
            }
        }
        return false;
    }
	public static boolean hasCycle2(ListNode head) {
		ListNode p1 = head,p2 = head;
		while (p2!=null && p2.next!=null) {
			p1 = p1.next;
			p2 = p2.next.next;
			if(p1 == p2){
				return true;
			}
		}
        return false;
    }
}

leet881.救生艇

因为船的数量要尽可能少,所以能坐两个人就坐两个人。体重越高,就越难与人同一艘船,为了让胖子也能尽量乘两人船,所以优先给最胖的人安排最瘦的。

因此,先对体重排序。

1.两个指针从两端向内逐步移动,对取得的每个people[a]和people[b]求和。

2.如果和在limit内,则共一船,两指针都内移,船数量++;否则胖子单独一船(目前最轻的都无法和他共船,那不可能存在他的搭档)。轻指针不动,重指针内移一步,船数量++。

3.需要注意的仍然是循环条件,因为两个指针都在移动,如果用a==b可能会错过,所以用a<=b(当相等时,1.这个人体重*2<limit,独自坐船,下一次循环b+1等于a-1,结束;2.体重*2>limit,胖的胖指针左移坐船,瘦子不动,下一次循环b就等于a-1,结束)。

public int numRescueBoats(int[] people, int limit) {
        int result = 0;
        Arrays.sort(people);
        int a = 0,b = people.length-1;
        while (a < b) {
        	if(people[a]+people[b]<=limit){
        		a += 1;b -= 1;
        		result += 1;
        	}
        	else {
				b -= 1;
				result += 1;
			}
		}
        if(a == b) result+=1;
		return result;
    }

(题库来自B站爱学习的饲养员,一个声音超好听的小姐姐QAQ)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值