[刷题记录]牛客面试笔刷TOP101

牛客笔试算法必刷TOP101系列,每日更新中~(主要是记录自己的刷题,所以描述的可能不是很清楚

但如果刚好能帮助到你就更好了)

后续后头复习的时候,记得是看正解啊,别对着错的例子傻傻看了...

目录

1.合并有序链表2023.9.3

2.链表是否有环2023.9.4

3.判断链表中环的入口点

4.链表中倒数最后K个节点2023.9.5

5.删除链表的倒数第n个节点

6.两个链表的第一个公共节点2023.9.6

7.链表相加

8.单链表的排序23.9.7

 9.判断一个链表是否为回文结构

10.链表的奇偶(节点)重排23.9.8

11.删除有序链表中的重复元素


1.合并有序链表2023.9.3

合并两个排序的链表_牛客题霸_牛客网 (nowcoder.com)

题意大致为:

将两个链表中的元素按照从小到大的顺序合并成为一个链表.

所给予的条件:

给出的所要合并的链表都是从小到大顺序排列的.

思路:

创建一个新的头节点来方便组装新的链表.分别用两个指针遍历两个链表,比较两个指针所在的节点,较小的节点先一步存放到新链表中,并且相应的指针向后移动一位.

移动后的指针所在的节点再与先前较大的未移动的节点进行比较,循环进行上面的操作.

直到任一链表遍历完毕,再把另一没遍历完的链表剩下的节点连接到新链表的尾巴. 

错解:

public ListNode Merge (ListNode pHead1, ListNode pHead2) {// write code hereListNode fakeHead = new ListNode(-1);ListNode cur = fakeHead;while(pHead1.next != null || pHead2.next != null){//我怎么用了或呢!!!//明明是把链表都遍历一遍不要管他nextif(pHead1.val <= pHead2.val){cur.next = pHead1;cur = cur.next;pHead1 = pHead1.next;}else{cur.next = pHead2;cur = cur.next;pHead2 = pHead2.next;}}if(pHead1.next == null){//上面错,下面跟着错了.cur.next = pHead2;}if(pHead2.next == null){cur.next = pHead1;}return fakeHead.next;}

刚开始,可能脑袋真的不好使了.

明明想的是,要把链表都遍历完整一遍,分别拿每一个节点跟另一个链表的节点进行比较.结果while循环中写的却是.next.还想不出问题在哪里真的是罪过.

还有while循环条件中的连接符号居然用的||.

只要有一个链表遍历完了就结束循环,所以要用&&啊啊啊!!!

真的是出师未捷身先死,下面好好加油吧.

正确题解:

起码脑子里的思路是对的,就是想的跟写的对不太上...

import java.util.*;/** public class ListNode {*   int val;*   ListNode next = null;*   public ListNode(int val) {*     this.val = val;*   }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param pHead1 ListNode类 * @param pHead2 ListNode类 * @return ListNode类*/public ListNode Merge (ListNode pHead1, ListNode pHead2) {// write code hereif(pHead1 == null){return pHead2;}if(pHead2 == null){return pHead1;}ListNode fakeHead = new ListNode(-1);ListNode cur = fakeHead;while(pHead1 != null && pHead2 != null){//这里之前用了||if(pHead1.val <= pHead2.val){cur.next = pHead1;pHead1 = pHead1.next;}else{cur.next = pHead2;pHead2 = pHead2.next;}cur = cur.next;}if(pHead1 == null){cur.next = pHead2;}else{cur.next = pHead1;}return fakeHead.next;}
}

2.链表是否有环2023.9.4

判断链表中是否有环_牛客题霸_牛客网 (nowcoder.com)

题意:

判断链表中是否有环,环所指的是:链表中节点的next存放此节点先前节点的地址.

给予的条件:

普通链表一个

思路:

这道题先前有学习过,我学到了两种解法.

①:用快慢指针的方法,快指针的速度是慢指针的两倍.在完全遍历完链表先前,如果快指针与慢指针相遇了,则证明此链表中含有环.反之,证明没有.(闭环追及问题)

②:用HashSet的方法,将链表进行遍历,把遍历到的节点的地址存放到set当中.如果链表有环则必定会有节点重复存放第二次,就可以用contains来判断有没有环.

public static boolean hasCycle(ListNode head) {ListNode fast = head;ListNode slow = head;//因为fast一次走两步,在while循环中就要判断能否有足够的位置够一次走两步//首先要判断fast!=null,看是否遍历完成,如果没有再看其后面有没有节点while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;if(slow == fast){return true;}}return false;}

3.判断链表中环的入口点

链表中环的入口结点_牛客题霸_牛客网 (nowcoder.com)

思路:首先是要判断链表有没有环,有环才能进行后面的操作

public ListNode EntryNodeOfLoop(ListNode pHead) {ListNode fast = pHead;ListNode slow = pHead;boolean check = false;//首先要判断链表有没有环while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;if(fast == slow){check = true;break;}}if(!check){//证明没有环return null;}slow = pHead;while(slow != fast){slow = slow.next;fast = fast.next;}return fast;}

4.链表中倒数最后K个节点2023.9.5

链表中倒数最后k个结点_牛客题霸_牛客网 (nowcoder.com)

题意:

根据给出的K,来返回链表中倒数第K个节点及其往后的所有节点.

思路:(有误)

这个题目以前写过了.

用的是快慢指针的方式,倒数第一个与倒数第K个节点之间相差K-1个节点.

所以,可以先让快指针从头节点走k-1步,再让慢指针从头节点开始,与快指针一齐一次走一步,直到快指针到达了末尾节点,此时慢指针所在的节点就是倒数第K个节点.

将慢指针所在的节点返回即可. 

纠正:

其实这里的本质是,控制两端的距离,再平行的进行移动.

快指针其实移动k个节点会好一点,

错解:

这里写的是移动k个节点了,跟想的时候不一样.如果是移动k个节点,看的是末尾后一个位置即空节点与倒数第K个节点的位置距离.

例如,倒数第三个节点,与空节点相差的距离是3.即倒数第三个节点要移动3次才能到达空节点的位置.

先判定再移动是为了能预防出现快指针走过头,走到了null,直接返回null却没有返回slow的情况

如果链表长5,求倒数第6个节点的时候,就会出现.

public ListNode FindKthToTail (ListNode pHead, int k) {if(pHead == null){return null;}// write code hereListNode fast = pHead;ListNode slow = pHead;for(int i = 0; i < k; i++){fast = fast.next;if(fast == null){return null;//主要是这里的问题,//因为倒数的k刚好为链表的长度,而fast是从头节点1开始//走到空指针之后就直接返回了//其实应该把if判定条件放到移动指针的上面//而且在外面加一个判断k是否合法的条件//当k小于0或等于0时返回null.}}while(fast != null){//fast要在尾巴节点停下来fast = fast.next;slow = slow.next;}return slow;}

正解:

2023.9.7补充一下,for循环里面的if主要是为了防止越界的,证明当前fast指针指向的节点不为空,可以继续往下走.是作为条件而不是判断,所以要放在上面而不是下面.

public ListNode FindKthToTail (ListNode pHead, int k) {if(pHead == null){return null;}// write code hereListNode fast = pHead;ListNode slow = pHead;for(int i = 0; i < k; i++){if(fast == null){return null;}fast = fast.next;}while(fast != null){//fast要在尾巴节点停下来fast = fast.next;slow = slow.next;}return slow;}

5.删除链表的倒数第n个节点

删除链表的倒数第n个节点_牛客题霸_牛客网 (nowcoder.com)

嗨呀,这个跟上面一起写的.简单啦,我就不信我会错.

思路(否决):

既然是删除,肯定要找到被删除的节点的前驱与后驱.再将他们连接起来.

找到倒数第n个节点,继续用快慢指针的方式来找.

有一个问题,slow的位置恰好倒数第n个的位置,那么其前驱我们就不能知道了.

所以要找倒数第n个位置的前一个,那么slow与fast之间的距离就会增加一位.变成了fast走n+1

还想到了,可能会删除头节点这种情况,想在fast移动之后加上一个判定条件 

思路(第二版):

觉得上面的太麻烦了,还容易出错.因为上面的思路会存在越界的行为.

头节点会变动的题型还是创建一个假的头节点来存放比较好.再加上一个新的指针在slow指针的前一位变动,tmp就是前驱slow是倒数第n个fast是后驱.将tmp与fast连接起来就好了

public ListNode removeNthFromEnd (ListNode head, int n) {// write code hereListNode fast = head;ListNode slow = head;ListNode fakeHead = new ListNode(-1);fakeHead.next = head;ListNode tmp = fakeHead;// if(n <= 0){//     return null;// }  写完才看到,题目保证n一定有效for(int i = 0; i < n; i++){if(fast == null){//走过头了return null;}fast = fast.next;}while(fast != null){fast = fast.next;slow = slow.next;tmp = tmp.next;}tmp.next = slow.next;return fakeHead.next;}

6.两个链表的第一个公共节点2023.9.6

两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com)

思路:

也是炒冷饭了.想到的是先遍历链表,分别得到他们的长度.

用双指针的方式,对于较长的链表先走两个链表长度差的距离.

再让两个指针分别从链表出发,一次走一步直到null,如果其中两指针相对,则证明有公共节点,

然后还学到了第二个方法.

对比上面的方法的优点是:不用考虑哪一个链表比较长,也不用额外写代码来得到链表的长度.虽然他们的本质都是双指针的方式.

就像下图的一样,直接让两个指针从两个链表的头节点开始一起往下走,任一一个指针遍历完所在的链表后,来到空节点时则会跳转到另一条链表的头节点开始遍历.

观察下面的图我们可以发现,这样就能消除链表长度导致的长度差.

public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {ListNode l1 = pHead1;ListNode l2 = pHead2;while(l1 != l2){if(l1 == null){l1 = pHead2;}else{l1 = l1.next;}if(l2 == null){l2 = pHead1;}else{l2 = l2.next;}}return l1;}

7.链表相加

链表相加(二)_牛客题霸_牛客网 (nowcoder.com)

思路:

我只能想到把链表都给翻转了才进行后面的操作.

然后创建一个新的头节点,创建新的节点.如果现在相加的节点个位溢出了就要移动到下一位去.

先写写看吧.

错解(愚蠢的错误):

最后一个例子没过去,好可惜.

努力找找看哪里错了吧...我看别人的代码好优雅噢.我的有点不堪.

public ListNode addInList (ListNode head1, ListNode head2) {// write code here//先翻转两个链表head1 = rever(head1);head2 = rever(head2);ListNode fakeHead = new ListNode(-1);//创建两个指针来遍历链表ListNode l1 = head1;ListNode l2 = head2;ListNode cur = fakeHead;//遍历新链表//存储溢出int count = 0;while(l1 != null && l2 != null){int tmp = l1.val + l2.val + count;if(tmp >= 10){tmp -= 10;//溢出了,得留到下一个.count = 1;}else{count = 0;}ListNode node = new ListNode(tmp);cur.next = node;cur = node;l1 = l1.next;l2 = l2.next;}while(l1 != null){int tmp = l1.val + count;if(tmp >= 10){tmp -= 10;count = 1;}else{count = 0;}ListNode node = new ListNode(tmp); cur.next = node;cur = node;l1 = l1.next;}while(l2 != null){int tmp = l2.val + count;if(tmp >= 10){tmp -= 10;count = 1;}else{count = 0;}ListNode node = new ListNode(tmp); cur.next = node;cur = node;l1 = l1.next;//什么东西啊,什么东西啊.对自己无语啦.,把这里改成l2就好了}if(count != 0){ListNode node = new ListNode(count);cur.next = node;cur = node;}return rever(fakeHead.next);}public ListNode rever(ListNode head){ListNode cur = head.next;ListNode pre = head;while(cur != null){ListNode curNext = cur.next;cur.next = pre;pre = cur;cur = curNext;}head.next = null;return pre;}

正解:

在错解里的代码改了.糊涂啊糊涂 

8.单链表的排序23.9.7

单链表的排序_牛客题霸_牛客网 (nowcoder.com)

思路(没想到):

一开始我只想到了把链表放到数组里面,在数组中进行排序之后再赋值到链表上.但是感觉不怎么好,又看到了题解里面说的用分治的思想,其实就是归并排序嘛.但是我内心会对递归有一定的抵触心理...但还是认真看了一遍题解,也自己动手画了一遍图.思路是清晰了,但不知道代码写得怎么样.先动手看看吧.

public ListNode sortInList (ListNode head) {// write code here//既然是用归并排序递归的思路://递归首先要考虑的是其结束的条件.//当只剩一个节点或没有节点的时候结束拆链表的递归操作if(head == null || head.next == null){return head;//返回当前节点}//先找到链表的中间点,进行拆.//找中间点用到了快慢指针的思想,再加上一个中间点的前驱节点才能进行拆除ListNode left = head;ListNode mid = head.next;ListNode right = mid.next;while(right != null || right.next != null){//因为要考虑链表节点个数的奇偶情况//奇数个的时候right指针走到尾巴节点就该停下来了,再继续走两步会越界//所以是right.next!=null的情况//偶数个的时候right指针可以走到尾巴节点的后一个空节点//还有就是因为right一次走两步的关系,需要判断能否还有足够的节点left = left.next;mid = mid.next;right = right.next.next;}//走完了,此时mid来到了中间节点的位置,left是mid的前驱节点的位置//别忘了head//此时前半段链表就被head和left所包裹//后半段链表就被mid与right所包裹//就要将他们分开了left.next = null;//继续调用来递归ListNode lhead = sortInList(head);//递归前半段ListNode rhead = sortInList(mid);//递归后半段//将他们进行排序//写一个排序的方法return sort(lhead,rhead);}public ListNode sort(ListNode p1,ListNode p2){//此处用双指针的方式,来分别遍历两个链表//就跟归并排序里的一样了//还要判断谁空了就返回另一半if(p1 == null){return p2;}if(p2 == null){return p1;}//重新创建一个新的链表来存储ListNode cur = new ListNode(-1);while(p1 != null && p2 != null){if(p1.val > p2.val){cur.next = p2;p2 = p2.next;}else{cur.next = p1;p1 = p1.next;}}//如果有剩余的节点没有遍历到,就直接加上去if(p1 != null){cur.next = p1;}else{cur.next = p2;}return cur.next;//最后返回排好序的链表}

正解:

都没有什么大错误,就是有一些逻辑上的不清楚.

也算是对递归这个心魔没那么恐惧了吧...

public ListNode sortInList (ListNode head) {// write code here//既然是用归并排序递归的思路://递归首先要考虑的是其结束的条件.//当只剩一个节点或没有节点的时候结束拆链表的递归操作if(head == null || head.next == null){return head;//返回当前节点}//先找到链表的中间点,进行拆.//找中间点用到了快慢指针的思想,再加上一个中间点的前驱节点才能进行拆除ListNode left = head;ListNode mid = head.next;ListNode right = mid.next;while(right != null && right.next != null){//错误1:调试后发现错误了||//因为要考虑链表节点个数的奇偶情况//奇数个的时候right指针走到尾巴节点就该停下来了,再继续走两步会越界//所以是right.next!=null的情况//偶数个的时候right指针可以走到尾巴节点的后一个空节点//还有就是因为right一次走两步的关系,需要判断能否还有足够的节点left = left.next;mid = mid.next;right = right.next.next;}//走完了,此时mid来到了中间节点的位置,left是mid的前驱节点的位置//别忘了head//此时前半段链表就被head和left所包裹//后半段链表就被mid与right所包裹//就要将他们分开了left.next = null;//继续调用来递归ListNode lhead = sortInList(head);//递归前半段ListNode rhead = sortInList(mid);//递归后半段//将他们进行排序//写一个排序的方法return sort(lhead,rhead);}public ListNode sort(ListNode p1,ListNode p2){//此处用双指针的方式,来分别遍历两个链表//就跟归并排序里的一样了//还要判断谁空了就返回另一半if(p1 == null){return p2;}if(p2 == null){return p1;}//重新创建一个新的链表来存储ListNode head = new ListNode(-1);//补充3:这里忘记加一个遍历的指针了//直接用头节点去接了怪不得返回只有一个节点ListNode cur = head;while(p1 != null && p2 != null){if(p1.val >= p2.val){//补充2 加一个=cur.next = p2;p2 = p2.next;}else{cur.next = p1;p1 = p1.next;}cur = cur.next;//补充1}//如果有剩余的节点没有遍历到,就直接加上去if(p1 != null){cur.next = p1;}else{cur.next = p2;}return head.next;//最后返回排好序的链表}

 9.判断一个链表是否为回文结构

判断一个链表是否为回文结构_牛客题霸_牛客网 (nowcoder.com)

思路:

找到中间的节点,将后半段链表进行翻转.

用双指针的形式,从开头与中间开始遍历节点.如果两者不一样,则证明为不是回文结构.

 错解:

不是很明白出什么问题了,先放到idea调试看看

主要是翻转之后与前半段的链接没有处理好.

我想实现的是指针分别遍历,没有给他们设null,直到他们相遇或者在偶数情况下在相邻的时候结束循环.

错的原因写在相应的注释里了,链表题还是要好好画图啊.还有记得理清一下循环结束的条件,是用||还是&&

public boolean isPail (ListNode head) {// write code here//先用双指针的形式找到中间节点,如果是偶数个节点,就找中间靠右的节点if(head == null || head.next == null){return true;//如果只有一个节点或者为空则}ListNode slow = head;ListNode fast = head;boolean count = true;while(fast != null && fast.next != null){slow = slow.next;fast = fast.next.next;}//此时slow为中间节点//这里本质上还是多此一举了,如果是奇数个直接从中间开始翻转就好了//这里的想法也是想把中间节点与翻转后的末尾进行连接,让两个指针能够相遇//但是顺序错了,而且这样就会太复杂if(fast != null){//证明为奇数个数,中间节点向后走一个ListNode mid = slow;slow = slow.next;slow.next = mid;}//翻转后半段slow = reverse(slow);while(head != slow || head.next != slow){//还要你,我最近怎么老是用错||与&&if(head.val != slow.val){count = false;break;}head = head.next;slow = slow.next;}return count;}public ListNode reverse(ListNode head){ListNode cur = head.next;ListNode pre = head;while(cur != null){ListNode curNext = cur.next;cur.next = pre;pre = cur;cur = curNext;}return pre;}

正解:

还是得自己调试和画图才能写出来,下次加油嗷.

public boolean isPail (ListNode head) {// write code here//先用双指针的形式找到中间节点,如果是偶数个节点,就找中间靠右的节点if(head == null || head.next == null){return true;//如果只有一个节点或者为空则}ListNode slow = head;ListNode fast = head;boolean count = true;while(fast != null && fast.next != null){slow = slow.next;fast = fast.next.next;}//此时slow为中间节点//翻转后半段slow = reverse(slow);//得到的slow是翻转后的了,相当于链表的末尾while(head != slow && head.next != slow){//中间放个&&是同时照顾到链表节点的个数为奇偶情况if(head.val != slow.val){count = false;break;}head = head.next;slow = slow.next;}return count;}public ListNode reverse(ListNode head){ListNode cur = head.next;ListNode pre = head;while(cur != null){ListNode curNext = cur.next;cur.next = pre;pre = cur;cur = curNext;}return pre;}

10.链表的奇偶(节点)重排23.9.8

链表的奇偶重排_牛客题霸_牛客网 (nowcoder.com)

注意是链表的节点噢

思路(错误):

用双指针的形式,p1指针从head开始,p2从head.next开始.

都为一次走两步,p1遍历奇数节点,p2遍历偶数节点.

感觉能写出来,开心呢!

错解:

好像死循环了...但是我看不出来

debug后发现,主要是分开遍历分别把他们添加到新链表中会改变他们的next,导致在链表中形成环.

public ListNode oddEvenList (ListNode head) {// write code hereif(head == null || head.next == null){//只有一个节点的,直接返回return head;}ListNode p1 = head;ListNode p2 = head.next;ListNode fakeHead = new ListNode(-1);ListNode cur = fakeHead;//先遍历奇数节点while(p1 != null && p1.next != null){//debug后发现,是这里条件的问题//链表个数为奇数个时p1会在最后一个节点停下来//但是没有进行下面的操作,再走到下面的循环就会死循环//但不是主要的问题...cur.next = p1;p1 = p1.next.next;cur = cur.next;}while(p2 != null && p2.next != null){cur.next = p2;p2 = p2.next.next;cur = cur.next;}cur.next = null;return fakeHead.next;}

正解:

可以一起遍历,两个指针作为相互的下一步的接口.

p1.next = p2.next;奇数的next变成偶数的next,偶数的next是下一个奇数位

然后p1 = p2.next来到刚刚存放的奇数位.

p2.next = p1.next.偶数的next变成奇数的next,奇数的next是下一个偶数位.

就这样把奇数和偶数分开遍历了一遍.并把他们都连接起来了.

最后只要把连接好的偶数位放到奇数位的后边

public ListNode oddEvenList (ListNode head) {// write code hereif(head == null || head.next == null){//只有一个节点的,直接返回return head;}ListNode p1 = head;ListNode p2 = head.next;//分别把奇数位与偶数位交叉串起来ListNode p2Head = p2;while(p2 != null && p2.next != null){//因为p2是先遍历的节点,所以以其为结束条件p1.next = p2.next;p1 = p2.next;p2.next = p1.next;p2 = p1.next;}//再把偶数放到奇数后面p1.next = p2Head;return head;}

11.删除有序链表中的重复元素

删除有序链表中重复的元素-I_牛客题霸_牛客网 (nowcoder.com)

思路:

如果下一个节点的val是相同的就while一路next直到下一个不同样,再把他连接上.

用双指针的方式?

public ListNode deleteDuplicates (ListNode head) {// write code hereif(head == null){return head;}ListNode p1 = head;ListNode p2 = head.next;while(p2 != null){if(p1.val == p2.val){p2 = p2.next;}else{p1.next = p2;p1 = p1.next;p2 = p1.next;}}return head;}

 

正解:

思考了一下后,发现.

永远是以p2为结束条件,所以跳出循环的时候p2一定为null.

那最后不管p1的next是怎么样的,都把他给上p2即null就不会出错啦.

public ListNode deleteDuplicates (ListNode head) {// write code hereif(head == null){return head;}ListNode p1 = head;ListNode p2 = head.next;while(p2 != null){if(p1.val == p2.val){p2 = p2.next;}else{p1.next = p2;p1 = p1.next;p2 = p1.next;}}p1.next = p2;return head;}

12.删除有序链表中的重复元素||23.9.9

删除有序链表中重复的元素-II_牛客题霸_牛客网 (nowcoder.com)

思路:

只能想到用map的方法来写,计算出现的频率留下只出现一次的节点.

双指针的方式尝试了,但是写不出来..

正解:

双指针的主要思路是,先看后动.

用一个指针p2遍历链表,查看其当前val是否与下一个节点的val相同.

如果相同就next,直到遇到下一个与其val不同的节点.

这时,p2就会在相同节点的最后一个停下来.

然后观察负责连接的指针p1与p2的关系.

如果p1的下一个就是p2,那么证明两个节点为相邻的节点,p1就可以移动一步

如果p1的下一个不是p2,那么证明刚刚p2遇到了重复的元素并进行了跳过.就需要连接p2的next节点(p2会在相同val节点的末端停下).

最后p2继续遍历链表

public ListNode deleteDuplicates (ListNode head) {// write code hereif(head == null || head.next == null){return head;}//因为头节点可能会被删掉,所以加一个假的头节点ListNode fakeHead = new ListNode(-1);fakeHead.next = head;ListNode p1 = fakeHead;ListNode p2 = head;while(p2 != null){//p2遍历链表,p1用来连接while(p2.next != null && p2.val == p2.next.val){//会在相同点的最后一个停下来p2 = p2.next;}if(p1.next == p2){p1 = p1.next;}else{p1.next = p2.next;}p2 = p2.next;}return fakeHead.next;}

13.二分查找-| 23.9.10

二分查找-I_牛客题霸_牛客网 (nowcoder.com)

思路:

让我回忆一下二分查找是什么...

在升序数组中,要找到一个target.

三个指针,left,mid,right.

先查看mid所在的数值为多少,如果mid比target小,则证明target在右半边.left = mid + 1,mid = (left+right)/2.

如果mid比target大,则证明target在左半边,right = mid - 1,mid = (left+right)/2.

如果mid == target则返回mid.

public int search (int[] nums, int target) {if(nums.length == 0){return -1;}int left = 0;int right = nums.length;int count = -1;while(left <= right){//这里记得要给等号噢,只剩两位数的时候可能会遍历不到int mid = (left + right) / 2;if(nums[mid] == target){count = mid;break;}else if(nums[mid] > target){right = mid - 1;}else if(nums[mid] < target){left = mid + 1;}}return count;}

14.二维数组中的查找

二维数组中的查找_牛客题霸_牛客网 (nowcoder.com)

思路:

升序的二维数组...

先从第一个数组末尾开始向左遍历

遇到比target大的,就向左移动一位.

遇到比target小的,就向下移动一位.

public boolean Find (int target, int[][] array) {// write code hereint y = array[0].length - 1;//得到一行的长度int x = 0;//得到一共有多少行int n = array.length - 1;while(x <= n && y >= 0){if(array[x][y] == target){return true;}else if(array[x][y] > target){y--;}else if(array[x][y] < target){x++;}}return false;}

15寻找峰值

寻找峰值_牛客题霸_牛客网 (nowcoder.com)

思路:

想直接暴力模拟,但是会越界.

正解:

采用二分查找的方法,其实我一开始也想到了用二分查找.但判断的是两个边界与mid的关系,而不是mid与周围元素的关系.

这个向左收缩,right = mid 而不是mid-1

public int findPeakElement (int[] nums) {// write code hereif(nums.length == 1){return 0;}int left = 0;int right = nums.length - 1;int mid = 0;while(left < right){mid = (left + right) / 2;if(nums[mid] < nums[mid+1]){left = mid + 1;//如果mid的右边元素比mid大证明mid不可能是波峰//区间往右边收缩}else{//如果mid的左边元素比mid小,mid可能是波峰//所以不能-1跳过mid缩小区间了right = mid;}}return left;//不断缩小区间,直到两边界相等时,得到的为波峰}

16.比较版本号23.9.11

比较版本号_牛客题霸_牛客网 (nowcoder.com)

思路:

以'.'为分隔,获取数字.

每一个"."之间的数值进行比较.

注意的是,要比较一整个数.

例入:0.226与0.38.因为226大于38所以前面的版本号是久一点的.

public int compare (String version1, String version2) {// write code hereint len1 = version1.length();int len2 = version2.length();int i = 0;int j = 0;while(i < len1 || j < len2){//可以不关注之间的长度差,注意不越界就行int count1 = 0;while(i < len1){char ch = version1.charAt(i);//获取下标的字符if(ch == '.'){//如果是"."就跳过i++;break;}else{//如果不是就加起来,记得*10是为了进位count1 = (count1 * 10) +  ch - '0'; i++;}}int count2 = 0;while(j < len2){char ch = version2.charAt(j);if(ch == '.'){j++;break;}else{count2 = (count2 * 10) + ch - '0';j++;}}//此处的比较是按照"."来分割的,比较两个字符串同一位置整个修订号的大小if(count1 > count2){return 1;}else if(count1 < count2){return -1;}}return 0;}

17.二叉树的前序遍历

二叉树的前序遍历_牛客题霸_牛客网 (nowcoder.com)

思路:

递归的思路,前序是:中序,左节点,右节点

中序就是中间节点在前面,每次往下走一步就把当前root的val加入,然后才去遍历左再遍历右

public int[] preorderTraversal (TreeNode root) {// write code hereList<Integer> list = new ArrayList<>();preoder(list,root);int[] ret = new int[list.size()];for(int i = 0; i < list.size(); i++){ret[i] = list.get(i);}return ret;}public void preoder(List<Integer> list,TreeNode root){if(root == null){return;}list.add(root.val);preoder(list,root.left);preoder(list,root.right);}

18.二叉树的中序遍历

二叉树的中序遍历_牛客题霸_牛客网 (nowcoder.com)

思路:

跟前序遍历的思想差不多,中序嘛就是左节点在前面.

就要找左节点,走走走,遍历到最左下角的左节点.便把其加入,再一步一步回头.

public int[] inorderTraversal (TreeNode root) {// write code hereList<Integer> list = new ArrayList<>();inorder(list,root);int[] ret = new int[list.size()];for(int i = 0; i < list.size(); i++){ret[i] = list.get(i);}return ret;}public void inorder(List<Integer> list,TreeNode root){if(root == null){return;}inorder(list,root.left);//先遍历完左节点,再加入list.add(root.val);inorder(list,root.right);}

19二叉树的后序遍历

二叉树的后序遍历_牛客题霸_牛客网 (nowcoder.com)

思路:

都差不多嘛,后序就左 右 中.

先遍历左节点,再遍历右边的节点,最后加入

public int[] postorderTraversal (TreeNode root) {// write code hereList<Integer> list = new ArrayList<>();postorder(list,root);int[] ret = new int[list.size()];for(int i = 0; i < list.size(); i++){ret[i] = list.get(i);}return ret;}public void postorder(List<Integer> list, TreeNode root){if(root == null){return;}postorder(list,root.left);postorder(list,root.right);list.add(root.val);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/75834.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一分钟图情论文:《原始的布拉德福定律》

天津大学图书馆的研究馆员范铮先生&#xff0c;在《图书情报工作》第一期中发表了题为《原始的布拉德福定律》的文章&#xff0c;详细介绍了布拉德福定律的历史背景、调查统计数据、文献曲线以及理论推导等关键内容。这篇文章让我们能够深入了解布拉德福定律的本质和原始构想。…

概率论与数理统计学习笔记(7)——全概率公式与贝叶斯公式

目录 1. 背景2. 全概率公式3. 贝叶斯公式 1. 背景 下图是本文的背景内容&#xff0c;小B休闲时间有80%的概率玩手机游戏&#xff0c;有20%的概率玩电脑游戏。这两个游戏都有抽卡环节&#xff0c;其中手游抽到金卡的概率为5%&#xff0c;端游抽到金卡的概率为15%。已知小B这天抽…

Windows环境下Springboot3+Graalvm+Idea 打包成原生镜像 踩坑

https://github.com/oracle/graal/https://github.com/graalvm/graalvm-ce-builds/releases/对应关系graalvm-ce-java17-windows-amd64-X.X.X.zipnative-image-installable-svm-java17-windows-amd64-X.X.X.jar本人使用:graalvm-ce-java17-windows-amd64-23.0.1.zipnative-imag…

蓝桥杯官网练习题(纸牌三角形)

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 A,2,3,4,5,6,7,8,9 共 99 张纸牌排成一个正三角形&#xff08;A 按 1 计算&#xff09;。要求每个边的和相等。 下图就是一种排法。 这样的排法可能会有很多。 如果…

修改Docker镜像默认下载地址

1、安装完docker desktop后&#xff0c;先不要打开 2、新建目录 D:\ProgramData\Docker 3、在C:\Users\你的用户名\AppData\Local下&#xff0c;打开cmd或者powershell执行以下命令&#xff0c;命令语法略有不同。 powershell命令&#xff1a; cmd /c mklink /J Docker D:\Pro…

1-5 AUTOSAR数据交换文件ARXML

目录 一、Arxml文件 二、各类ARXML文件 一、Arxml文件 arxml文件是AUTOSAR&#xff08;Automotive Open System Architecture&#xff09;标准定义的XML文件&#xff0c;用于描述汽车电子系统中的软件组件、通信接口和参数配置等信息。 arxml文件的主要作用是在AUTOSAR架构下…

golang教程 beego框架笔记一

安装beego 安装bee工具 beego文档 # windos 推荐使用 go install github.com/beego/bee/v2master go get -u github.com/beego/bee/v2masterwindows使用安装bee工具时碰到的问题&#xff1b; 环境配置都没有问题&#xff0c;但是执行官网的命令&#xff1a;go get -u github…

打造高效的私密论坛网站:Cpolar内网穿透+HadSky轻量级搭建指南

文章目录 前言1. 网站搭建1.1 网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09;2.4 公网访问测试 总结 前言 经过多年的基础…

大数据和数据要素有什么关系?

大数据与数据要素之间存在密切的关系。大数据是指海量、多样化、高速生成的数据&#xff0c;而数据要素是指构成数据的基本元素或属性。数据要素包括但不限于数据的类型、结构、格式、单位、精度等。 大数据的产生和应用离不开数据要素的支持。数据要素确定了数据的基本特征和…

【网络基础】——HTTPS

目录 HTTPS背景知识 HTTPS是什么&#xff1f; 加密解密 为什么要加密 常见的加密方式 对称加密 非对称加密 数据摘要&&数据指纹 数字签名 HTTPS工作过程探究 方案1&#xff1a;只使用对称加密 方案2&#xff1a;只使用非对称加密 方案3&#xff1a;双方…

conda和Python的虚拟环境如何结合使用,以及二者之间到底有什么区别?

问题描述 今天在复现streamlit的代码时&#xff08;参考Streamlit 讲解专栏&#xff08;一&#xff09;&#xff1a;安装以及初步应用&#xff09;&#xff0c;根据这篇博文指导&#xff0c;要先用以下指令创建一个虚拟环境&#xff1a; # 创建虚拟环境&#xff08;使用venv&a…

【python】读取.dat格式文件

import binascii# 打开二进制文件以只读二进制模式 with open(EXCEL/文件.dat, rb) as file:binary_data file.read()print(binary_data)# 将二进制数据转换为十六进制字符串 hex_data binascii.hexlify(binary_data).decode(utf-8) # binary_data 现在包含了文件的二进制内容…

git标签基础

打标签:git可以给仓库历史中某个提交打上标签,以示重要,比较有代表人们会使用这个功能来标记发布结点(V1.0,V2.0) 列出本地标签: git tag --list git tag -l "V1.85*" 列出远端仓库的中所有标签 git ls-remote --tags给标签添加一些描述信息 git tag -a v1.3 -m …

热释电矢量传感器设计

1 概述 使用4个热释电传感器组成一个2X2的矩阵。通过曲线的相位差、 峰峰值等特征量来计算相关信息。本文使用STM32单片机设计、制作了热释电传感器矩阵&#xff1b;使用C#.NET设计了上位机软件。为以上研究做了试验平台。 2 硬件电路设计 2.1 热释电传感器介绍 热释电红外…

c++异步框架workflow分析

简述 workflow项目地址 &#xff1a; https://github.com/sogou/workflow workflow是搜狗开源的一个开发框架。可以满足绝大多数日常服务器开发&#xff0c;性能优异&#xff0c;给上层业务提供了易于开发的接口&#xff0c;却只用了少量的代码&#xff0c;举重若轻&#xff…

Fastjson_1.2.24_unserialize_rce漏洞复现

fastjson_1.2.24_unserialize_rce 说明内容漏洞编号CNVD-2017-02833漏洞名称FastJson < 1.2.24 远程代码执行漏洞评级高危影响范围1.2.24漏洞描述通过parseObject/parse将传入的字符串反序列化为Java对象时由于没有进行合理检查修复方案升级组件&#xff0c;打补丁&#xf…

9.11C高级day4

实现一个对数组求和的函数&#xff0c;数组通过实参传递给函数 sum0 function add() {for i in $*  #$*接收传来的所有参数do((sumi))doneecho $sum }#定义一个数组 arr(1 2 3 4 5 7 9)#向函数传参 add ${arr[*]}写一个函数&#xff0c;输出当前用户的uid和gid&#xff0c;并…

SQL6 查找学校是北大的学生信息

描述 题目&#xff1a;现在运营想要筛选出所有北京大学的学生进行用户调研&#xff0c;请你从用户信息表中取出满足条件的数据&#xff0c;结果返回设备id和学校。 示例&#xff1a;user_profile iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male…

干了三年的功能测试,让我女朋友跑了,太难受了...

简单概括一下 先说一下自己的情况&#xff0c;普通本科&#xff0c;19年通过校招进入深圳某软件公司&#xff0c;干了3年多的功能测试&#xff0c;21年的那会&#xff0c;因为大环境不好&#xff0c;我整个人心惊胆战的&#xff0c;怕自己卷铺盖走人了&#xff0c;我感觉自己不…

【RabbitMQ】介绍及消息收发流程

介绍 RabbitMQ 是实现 AMQP&#xff08;高级消息队列协议&#xff09;的消息中间件的一种&#xff0c;最初起源于金融系统&#xff0c;用于在分布式系统中存储转发消息&#xff0c;在易用性、扩展性、高可用性等方面表现不俗。 RabbitMQ 主要是为了实现系统之间的双向解耦而实…