每日算法220514链表顺位相加和有序链表合并

Posted 如何在5年薪百万

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日算法220514链表顺位相加和有序链表合并相关的知识,希望对你有一定的参考价值。

今日题目

  • 题目1: 把两个长短链表按照顺序每一位相加后返回新的链表(难)
  • 题目2: 把两个有序链表合并后返回新的有序链表(中)

今日心得

  • 直接看算法答案是不能提高算法水平的,算法最重要的就是解题思路而非编码。看了别人的思路去实现会少了最重要的部分。
  • 基本功就是数据结构的基本操作。比如链表结构以及如何遍历链表。如果这些知识都不具备。面试是不可能写出代码的,因为基本人你很难构思出如何遍历链表。

算法编码

链表结构

package linklist;

import java.util.List;

/**
 * @ClassName ListNode
 * @Description 单项链表
 * @Author kouryoushine
 * @Date 2022/5/13 23:23
 * @Version 1.0
 */
public class ListNode 
    int value;
    ListNode next;
    int length;

    public ListNode(int value) 
        this.value = value;
    


    public static ListNode randListNode(int maxLengh, int maxValue) 
        int first = (int) (Math.random() * maxValue);
        int length = (int) (Math.random() * maxLengh);
        ListNode listNode = new ListNode(first);// first节点
        ListNode tail = listNode;
        for (int i = 0; i < length; i++) 
            int val = (int) (Math.random() * maxValue);
            ListNode node = new ListNode(val);
            tail.next = node;
            tail = node;
        
        listNode.length=length+1;
        return listNode;

    


    public void printListNode() 
        ListNode head = this;
        System.out.println(" ");
        System.out.println("print list node ------------------------------");
        while (head != null) 

            System.out.print(head.value);
            head = head.next;
        

    

    public int listLength() 
        int length = 0;
        ListNode head = this;
        while (head != null) 
            length++;
            head = head.next;
        
        return length;

    





两个数字链表相加

package linklist;

import java.util.List;

/**
 * @ClassName AddTwoNumberListNode
 * @Description 两个数字链表相加
 * 链表L: 3->8->9->9->9
 * 链表S: 1->8->3
 * 加法:逐位相加,大于10则进1  ,  4->6->3->0->0->1
 * @Author kouryoushine
 * @Date 2022/5/13 23:25
 * @Version 1.0
 */

//难点在于理解构思如下算法
//对数器不知道怎么写
public class AddTwoNumberListNode 
    public static void main(String[] args) 
        ListNode list1 = ListNode.randListNode(10, 9);
        list1.printListNode();
        ListNode list2 = ListNode.randListNode(10, 9);
        list2.printListNode();
        ListNode result = addTwoNumberList(list1, list2);
        result.printListNode();

    


    public static ListNode addTwoNumberList(ListNode list1, ListNode list2) 
        //获取
        int length1 = list1.listLength();
        int length2 = list2.listLength();
        ListNode l = length1 > length2 ? list1 : list2; //长链表的头部
        ListNode s = l == list1 ? list2 : list1; //短链表的头
        ListNode curS = s;//初始定位在短链
        ListNode curL = l;//初始定位在长链头部

        ListNode lastL = null;//长节点的最后一个位置
        int carry = 0;//进位非常重要
        //将相加过程分为三个阶段
        //phase1: shortlist not null
        while (curS != null) 
            int sum = curL.value + curS.value + carry;
            carry = sum >= 10 ? 1 : 0;//是否进位  等价于 sum/10
            curL.value = sum % 10; //当前位置的结果
            curS = curS.next; //下标右移动
            curL = curL.next; //下标右移动
        
        //phase2: longlist not null
        while (curL != null)   //继续读长数组
            int sum = curL.value + carry;
            carry = sum >= 10 ? 1 : 0;//是否进位
            curL.value = sum % 10; //当前位置的结果
            lastL = curL; //最后一位
            curL = curL.next; //下标右移动
        

        //phase3: after read all
        if (carry == 1)  //需要把carry作为新的节点添加到尾部
            ListNode lastnode = new ListNode(carry);
            lastL.next = lastnode;
        

        return l;// 返回长链表(用长链表保存相加的结果)


    




有序链表合并,合并后依然是有序链表

package linklist;

import java.util.ArrayList;

/**
 * @ClassName MergeOrderedListNode
 * @Description 有序链表合并,合并后依然是有序链表
 * * 链表1: 1->3->4->6->7
 * * 链表2: 1->2->6
 * 结果:  1-1-2-3-4-6-6-7
 * @Author kouryoushine
 * @Date 2022/5/14 0:56
 * @Version 1.0
 */
public class MergeOrderedListNode 
    //感觉比较简单,链表遍历熟悉的话
    public static void main(String[] args) 
        ListNode left=new ListNode(1);
        ListNode left1 =new ListNode(3);
        ListNode left2 =new ListNode(4);
        ListNode left3 =new ListNode(6);
        ListNode left4 =new ListNode(7);
        left.next=left1;
        left1.next=left2;
        left2.next=left3;
        left3.next=left4;
        left.printListNode();
        ListNode right=new ListNode(1);
        ListNode right1 =new ListNode(2);
        ListNode right2 =new ListNode(6);
        right.next=right1;
        right1.next=right2;
        right.printListNode();
        ListNode merge = mergeOrderedListNode2(left, right);
        merge.printListNode();

//        ArrayList<ListNode> listNodes = mergeOrderedListNode(left, right);
//        for (int i = 0; i < listNodes.size(); i++) 
//            System.out.println(listNodes.get(i).value);
//        


    

    /**
     * 借助队列自己实现了一个版本,队列可以用ArrayList代替
     * @param left
     * @param right
     * @return
     */
    public static ArrayList<ListNode> mergeOrderedListNode(ListNode left, ListNode right) 
        ListNode curL = left;
        ListNode curR = right;
        ArrayList<ListNode> linkedQueue = new ArrayList<>();
        while (curL != null || curR != null)  //任意一个有值就继续读
            int valL = curL != null ? curL.value : Integer.MAX_VALUE; //为空则给最大值
            int valR = curR != null ? curR.value : Integer.MAX_VALUE; //为空则给最大值
            if (valL == valR) 
                linkedQueue.add(curL);
                linkedQueue.add(curR);
                curL = curL.next;
                curR = curR.next;
             else if (valL > valR) 
                linkedQueue.add(curR);
                curR = curR.next;
             else 
                linkedQueue.add(curL);
                curL = curL.next;
            

        

        return linkedQueue;
    


    /**
     * 看一下链表的标准算法,比自己想的好很多。看答案很简单,自己构思出来不容易
     */

    public static ListNode mergeOrderedListNode2(ListNode left,ListNode right)
        //选择最小的头部作为最终头部
        ListNode head = left.value<=right.value?left:right;
        ListNode curL= head==left?left.next:left; //跳过头部
        ListNode curR= head==right?right.next:right;  //跳过头部
        ListNode pre =head;//缓存前一个节点

        while (curL!=null && curR!=null)//两边都有值时比较

            if(curL.value<=curR.value)
                pre.next=curL;
                pre=curL;
                curL=curL.next;
            else 
                pre.next=curR;
                pre=curR;
                curR=curR.next;
            

            pre.next=curL==null?curR:curL;
        

        return head;
    



以上是关于每日算法220514链表顺位相加和有序链表合并的主要内容,如果未能解决你的问题,请参考以下文章

每日算法220514链表顺位相加和有序链表合并

小Y学算法⚡️每日LeetCode打卡⚡️——12.合并两个有序链表

leetcode 每日一题 21. 合并两个有序链表

《LeetCode之每日一题》:285.合并两个有序链表

《LeetCode之每日一题》:285.合并两个有序链表

《LeetCode之每日一题》:137.合并两个有序链表