笔试之链表总结

链表一般也是笔试经常考的一个内容之一,之前参加华为笔试没准备好,上来一个链表把我整蒙了,所以就来总结一下。

首先解题建议和技巧:链表其实有点抽象,尽量多画图,然后利用虚拟头指针,快慢指针,多指针等等;

常见题型:

          

 

          这种首先就要利用到虚拟头结点,然后再创建一个尾结点,遍历链表尾结点不断的指向不等于目标值得结点即可,代码如下,需要注意的是尾结点cur指向的结点在变,cur也要移动,因为它是尾结点。

      

    public ListNode removeElements(ListNode head, int val) {
        ListNode headNode = new ListNode(-1);
        ListNode cur = headNode;
        while(head != null){
            if(head.val != val){
                cur.next = head;//让headnode也有所指
                cur = head;//
            }
            head = head.next;
        }
        cur.next = null;
        return  headNode.next;
    }

               

 

                   这个题主要就是直接对位相加,注意要满十进位和空节点即可,代码如下:总结一点小知识,求一个数的个位直接对10取余数,求十位则除以10即可得到,另外要注意遍历两个链表的时候,其中一个出现空节点的时候无法取到该结                   点的值,所以要先判断。

    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       if(l1 == null) return  l2;
       if(l2 == null) return  l1;
       ListNode dummyHead = new ListNode(0);
       ListNode cur = dummyHead;
        int res = 0;
       while(l1 != null || l2 != null){
           int v1 = 0;
           int v2 = 0;
           if(l1 != null){
               v1 = l1.val;
           }
           if(l2 != null){
               v2 = l2.val;
           }
           int sum = l1.val + l2.val + res;
            res = sum / 10;
           sum = sum % 10;
           cur.next = new ListNode(sum );
           l1 = l1.next;
           l2 = l2.next;
       }
       if(res > 0) cur.next = new ListNode(res );
       return  dummyHead.next;
    }

 

     

 

 

 

可以有两种解法,常规的就是先计算两个链表的长度,再根据长度差去让长的链表先走一段。另外一种是一种很巧妙的方法,将短的链表拼接长的链表,长的同样也拼接上短的,比较即可,代码如下,建议使用第二种

   1, public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) return null; 
        int len1 = 1,len2 = 1;  
        ListNode p = headA;
        while(p.next != null){ 
            p = p.next;
            len1++;
        } 
        ListNode q = headB;      
        while(q.next != null){ 
            q = q.next;
            len2++;
        }
        if(p != q) return null;
        ListNode t1 = headA;
        ListNode t2 = headB;
        if(len1 > len2){
            int d = len1-len2;
           while(d != 0){
             t1 = t1.next;
              d--;
           }
        }else{
            int d = len2-len1;
            while(d != 0){
             t2 = t2.next;
             d--;
            }
        }
        while(t1 != t2){
            t1 = t1.next;
            t2 = t2.next;           
        }
    return t1;
    }
2,public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) return null;
        ListNode curA = headA;
        ListNode curB = headB;
        while(curA != curB){
            curA = (curA == null) ?headB:curA.next;
            curB = (curB== null) ?headA:curB.next;
        }
        return  curA;
    }

 

 

 

 这个题的解法其实用的还是创建链表的头结点和尾结点,然后尾结点不断的扩展,只不过此题中需要创建两个,一个用来放小于目标值,一个用来放大于等于的,然后再拼接到一起就可以了,注意需要将大于等于的尾结点指向null指针。代码如下:(其实这里可以慢慢形成一个小技巧,每次可以这样来“构造”要返回的链表)

 1     public ListNode partition(ListNode head, int x) {
 2         ListNode pre = new ListNode(0);
 3         ListNode pos = new ListNode(0);
 4         ListNode tailA  = pre;
 5         ListNode tailB = pos;
 6         while(head != null){
 7             if(head.val < x){
 8                 tailA.next = head;
 9                 tailA = head;
10             }else {
11                 tailB.next = head;
12                 tailB = head;
13             }
14             head = head.next;
15         }
16         tailB.next = null;
17         tailA.next = pos.next;
18         return pre.next;
19     }

 

 这个题可以先利用快慢指针找到中间节点,然后把后半部分的链表反转,再与前半部分直接比较即可,代码如下,这个题既可以练习快慢指针也可以练习反转链表,整体还是很好的

 1     public boolean isPalindrome(ListNode head) {
 2         if(head == null) return true;
 3         if(head.next.next == null) return head==head.next;
 4         ListNode mid = SearchMid(head);//寻找中间节点
 5         ListNode rHead = reverse(mid.next);//反转
 6         ListNode lHead = head;
 7         while(rHead != null){
 8             if(rHead.val != lHead.val){
 9                 return false;
10             }
11             rHead = rHead.next;
12             lHead = lHead.next;
13         }
14         return true;
15     }
16 
17     private ListNode reverse(ListNode head) {
18         ListNode pre = null;
19         ListNode cur = head;
20         while(cur != null){
21             ListNode next = cur.next;
22             cur.next = pre;
23             pre = cur;
24             cur = next;
25         }
26         return pre;
27     }
28     private ListNode SearchMid(ListNode head) {
29         ListNode slow = head;
30         ListNode fast = head;
31         while(fast != null){
32             fast = fast.next.next;
33             slow = slow.next;
34         }
35         return  slow;
36     }

 

posted @ 2020-08-03 20:58  tingting_lh  阅读(143)  评论(1)    收藏  举报