• 链表常见问题


    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
  • 相关阅读:
    一个简单的jsp自定义标签
    js正则表达式学习
    java获取当前日期等以及时区
    java日期处理SimpleDateFormat等
    一个炫酷的导航菜单,模仿别人写的
    后台管理界面自己写,模仿,更新中...
    信息收集-主机综合扫描工具的使用
    ms10_046_shortcut_icon_dllloader漏洞利用和ettercap dns欺骗
    如何成为一名黑客
    msf常用命令
  • 原文地址:https://www.cnblogs.com/little-YTMM/p/5446435.html
Copyright © 2020-2023  润新知