链表常见问题

1. 两数相加问题

给定两个链表,分别表示两个非负整数。他们的数字逆序存储在链表中,且每个节点只存储一个数字,计算两个数的和,并且返回和的链表头指针。

    如:输入:2->4->3 ,  5->6->4, 输出:7->0->8.

分析:因为两个数都是逆序存储的,因此可以从头往后加,而且每个节点存储的都是个位数,因此相加不会超过18。模拟两个数按位相加的过程就可以了。用一个额外的变量记录当前位相加是否有进位。

注意:

  • 当两个链表长度不相等时该怎么处理?
  • 最后一位是否有进位?

 

/**
     * 该算法计算两个逆序放置的链表的和,返回和的头指针
     * 如:输入:2->4->3 ,  5->6->4, 输出:7->0->8.
     * @param l1
     * @param l2
     * @return 
     */
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode h = new ListNode(-1);
        ListNode res = h;
        int flag = 0;
        ListNode p = l1, q = l2;
        while( p != null && q != null) {
            int temp = p.val + q.val;
            if(flag == 1)
                temp++;
            
            flag = temp / 10;
            temp %= 10;
            ListNode node = new ListNode(temp);
            res.next = node; 
            res = res.next;
            
            p = p.next;
            q = q.next;
        }
        while(p != null) {
            int temp = p.val;
            if(flag == 1) 
                temp++;
            
                
            flag = temp / 10;
            temp %= 10;
            ListNode node = new ListNode(temp);
            res.next = node; 
            res = res.next;
            p = p.next;
        }
        
        while(q != null) {
            int temp = q.val;
            if(flag == 1) 
                temp++;
            
            flag = temp / 10;
            temp %= 10;
            ListNode node = new ListNode(temp);
            res.next = node; 
            res = res.next;
            
            q = q.next;
        }
        if(flag == 1) {
            ListNode node = new ListNode(1);
            res.next = node;
        }
        return h.next;
    }
View Code

 

 

2. 链表部分翻转问题

给定一个链表,翻转该链表熊m到n的位置。要求直接翻转而非申请新空间。

    如:给定1->2->3->4->5,m=2, n=4, 返回1->4->3->2->5。

假设给出的参数满足:1 <= m <= n <= 链表长度。

 

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode reverseBetween(ListNode l, int m, int n) {
        if(l == null || l.next == null)
            return l;
        if(m == n)
            return l;
        ListNode l1 = new ListNode(-1);
        l1.next = l;
        int count = 0;
        ListNode head = l1;
        while(count + 1< m) {
            head = head.next;
            count++;
        }
        count++;
        ListNode t = head.next; 
        ListNode p, q;
        while(count < n) {
            p = t.next;
            q = head.next;
            head.next = p;
            t.next = p.next;
            p.next = q;
            count++;
        }
        return l1.next;
        
    
    }
}
View Code

 

 

 3. 链表去重问题

1) 给定排序的链表,删除重复元素,只保留重复元素第一次出现的结点。

如:给定:2->3->3->4->7->7->8, 返回:2->3->4->7->8.

    /**
     * 删除链表中所有重复的节点(重复的节点中保留一个)
     * @param l
     * @return
     */
    public ListNode deleteDuplicates(ListNode l) {
        if(l == null || l.next == null)
            return l;
        ListNode p = l;
        while(p != null && p.next != null) {
            if(p.val == p.next.val) {
                ListNode q = p.next;
                p.next = q.next;
                q.next = null;
            }
            else p = p.next;
        }
        return l;
    }
View Code

 

 

2)给定排序的链表,若发现重复元素,则重复元素全部删除。

 如:给定:2->3->3->4->7->7->8, 返回:2->4->8.

    /**
     * 该算法删除所有重复的节点,只要有重复,则全部删除
     * @param l
     * @return
     */
    public ListNode deleteDuplicatesII(ListNode l) {
        if(l == null || l.next == null)
            return l;
        ListNode head = new ListNode(-1);
        head.next = l;
        ListNode p = head;
        int temp = -1;
        while(p != null && p.next != null) {
            temp = p.next.val;
            ListNode q = p.next;
            boolean flag = false;
            while(q != null && q.next != null) {
                if(q.next.val == temp) {
                    flag = true;
                    q = q.next;
                }
                else break;
            }
            if(flag == true) {
                p.next = q.next;
                q.next = null;
            }
            else 
                p = q;
        }
        return head.next;
    }
View Code

 

 

 4. 链表划分问题

给定一个链表和一个值x,将链表划分成两部分,使得划分后小于x的节点在前,大于等于x的节点在后。在这两部分中要保持原链表汇总出现的顺序。

如:给定链表1->4->3->2->5->2和x=3,返回1->2->2->4->3->5.

/**
     * 给定一个链表和一个值x,将链表划分成两部分,使得划分后小于x的节点在前,大于等于x的节点在后。在这两部分中要保持原链表汇总出现的顺序。
     * @param head
     * @param x
     * @return
     */
    public ListNode partition(ListNode head, int x) {
        if(head == null || head.next == null)
            return head;
        
        ListNode head1 = new ListNode(-1);
        ListNode head2 = new ListNode(-1);
        ListNode h1 = head1, h2 = head2;
        ListNode p = head, q;
        while(p != null && p.next != null) {
            q = p.next;
            if(p.val < x) {
                h1.next = p;
                p.next = null;
                p = q;
                h1 = h1.next;
            }
            else {
                h2.next = p;
                p.next = null;
                p = q;
                h2 = h2.next;
            }
        }
    //    System.out.println(p.val);
        if(p.val < x) {
            h1.next = p;
            h1 = h1.next;
        }
        else {
            h2.next = p;
            h2 = h2.next;
        }
        h1.next = head2.next;
        return head1.next;
    }
View Code

 

 

5. 单链公共节点问题

给定两个单向链表,计算两个链表的第一个公共节点,若没有公共节点,则返回空。

分析:因为是单链表,所以如果两个链表中有公共结点,只要相遇了就不会分开。以短的链表的长度为基准。

/**
     * 给定两个单向链表,计算两个链表的第一个公共节点,若没有公共节点,则返回空。
     * @param head1
     * @param head2
     * @return
     */
    public ListNode getIntersectionNode(ListNode head1, ListNode head2) {
        int len1 = 0, len2 = 0;
        ListNode p1 = head1, p2 = head2;
        while(p1 != null) {
            p1 = p1.next;
            len1++;
        }
        while(p2 != null) {
            p2 = p2.next;
            len2++;
        }
        ListNode q1 = (len1 > len2) ? head1 : head2;
        int count = 0;
        while(count < Math.abs(len1 - len2)) {
            q1 = q1.next;
            count++;
        }
        
        ListNode q2 = (len1 <= len2) ? head1 : head2;
        while(q1 != null && q2 != null) {
            if(q1 == q2)
                return q1;
            else {
                q1 = q1.next;
                q2 = q2.next;
            }
            
        }
        return null;
    }
View Code

 

posted @ 2016-04-29 15:20  江湖小妞  阅读(366)  评论(0编辑  收藏  举报