目录
leet141.环形链表
链表问题,这里安排两种方案。
由于建议O(1)内存,所以不能对每一个节点是否被遍历过进行储存,于是有了方法一。
方法一:遍历过的节点将内容改为(题目中提示说明了
<= Node.val <=
),只要遍历到,那么说明成环了。
缺点,会破坏链表内容。实际中可能用不到(如果先复制一遍链表那就消耗了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)