两个非递减顺序表合并成一个非递减顺序表

简介: 两个非递减顺序表合并成一个非递减顺序表

两个非递减顺序表合并成一个非递减顺序表

  • 引入

以下这个例题的描述是关于合并两个有序的数组,然后合并之后同样也是一个非递减的顺序排列

但是我名这里讲的不是顺序表,而是封装成一个顺序表,但是我们这里的顺序表其实底层同样是一个数组,所以解题的思路完全相同,我们接下来要讲的就是“两个非递减顺序表合成的一个非递减的顺序表”。


合并两个有序数组

给你两个按非递减顺序排列的整数数组 nums 1 和 nums 2,另有两个整数 m 和 n ,分别表示 nums 1 和 nums 2 中的元素数目。


请你合并 nums 2 到 nums 1 中,使合并后的数组同样按非递减顺序排列。


注意:最终,合并后数组不应由函数返回,而是存储在数组 nums 1 中。为了应对这种情况,nums 1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。Nums 2 的长度为 n 。

  • 我们是合并两个顺序表,只是多了一个封装顺序表的步骤,但是该题目的解法思路是大同小异的。

❤️理清思路

  • 非递减顺序表
    非递减就是 “”,而顺序表就是线性表的一种,其逻辑结构是顺序结构,同时其物理结构也和逻辑结构相同的结构,在计算机中存储的物理结构也是连续存储的。
  • 题目要求
    将两个 “非递减顺序表” 合成一个非递减的顺序表,那么我们在实现这个方法的时候需要传两个 “非递减顺序表”作为参数,然后我们就在方法中对这两个顺序表进行操作。并且最后合成的顺序表同样非递减的顺序表,那么我们在实现方法的时候就必须保证顺序表的顺序一致
  • 思路
    自定义一个"顺序表"数据结构,然后定义一个方法 merge (),这个方法要求是传进去两个“非递减的顺序表对象” 参数,分别是 list 1 和 list 2;然后我们在方法中重新 new 一个“新的非递减的顺序表对象”newList,然后定义三个指针分别指向这三个顺序表下标为 0 的位置,利用“穿针引线法”,完成合并工作。
  • 穿针引线法
    我在这里将这种方式描述为 "穿针引线法"是因为真的很形象,但是其实如果是在链表中这样称呼,似乎更加合适。
    我们分别让 i 和 j 永远指向即将进行比较大小的数据元素,然后让 k 在新顺序表中永远都指向“索引等于顺序表有效长度“ 的地方,然后等待 i 和 j 比较的结果的数据元素的插入,直到任意一个顺序表遍历完,
    如果同时遍历完, 那么合并的工作做完了;如果其中一个顺序表遍历玩,而另外一个没有遍历完,那么就把更长的顺序表直接加到 newList 顺序表中。
    综上所述,就完成了两个非递减顺序表的合并工作。

🚀代码实现

package TextReport;  
import java.util.Arrays;  
public class MyArrayList {  
    //    存放数据的数组  
    public int[] elem;  
    //    记录数组的有效长度  
    public int usedSize;  
    //    常量,用来给数组初始化容量  
    public static final int DEFAULT_CAPACITY = 5;  
    //    构造方法  
    public MyArrayList() {  
        this.elem = new int[DEFAULT_CAPACITY];  
    }  
    public MyArrayList(int defaultSize) {  
        this.elem = new int[defaultSize];  
    }  
    //    打印顺序表的方法(顺序表中有几个有效元素就打印几个有效元素)  
    public void display() {  
        for (int i = 0; i < usedSize; i++) {  
            System.out.print(this.elem[i] + " ");  
        }  
        System.out.println();  
    }  
    //    输入(新增加元素,默认在顺序表的最后一个元素的下一个位置上新增)  
    public void add(int data) {  
        try {  
            if (isFull()) {  
                elem = Arrays.copyOf(elem, 2 * elem.length);  
            }  
        } catch (NegativeArraySizeException e) {  
            e.printStackTrace();  
        }  
        Elem[usedSize++] = data;  
    }  
    //    在指定位置索引为 pos 新增元素  
    Public void addPos (int data, int pos) {  
        //先判断下标是否合法  
        Try {  
            CheckedAddPos (pos);  
            If (isFull ()) {  
                Elem = Arrays.CopyOf (elem, 2 * elem. Length);  
            }  
            For (int i = usedSize - 1; i > pos; i--) {  
                Elem[i + 1] = elem[i];  
            }  
            Elem[pos] = data;  
            UsedSize++;  
        } catch (PosIndexIllegalException e) {  
            e.getMessage ();  
        }  
    }  
    //判断顺序表中是否包含某个元素  
    Public boolean contains (int data) {  
        For (int i = 0; i < usedSize; i++) {  
            If (data == elem[i]) {  
                Return true;  
            }  
        }  
        Return false;  
    }  
    //返回某个元素的在容器中的索引  
    Public int indexOf (int find) {  
        For (int i = 0; i < usedSize; i++) {  
            If (find == elem[i]) {  
                Return i;  
            }  
        }  
        Return -1;  
    }  
    //获取指定下标 pos 的值  
    Public int getPos (int pos) {  
        Int retVal = -1;  
        //检查 pos 是否合法  
        Try {  
            CheckGetPos (pos);  
            RetVal = elem[pos];  
            ;  
        } catch (PosIndexIllegalException e) {  
            e.getMessage ();  
        }  
        Return retVal;  
    }  
    //      删除第一次出现关键字 key 的方法  
    Public void remove (int key) {  
        //先获取第一次出现 key 元素的下标  
        Int index = indexOf (key);  
        If (index == -1) {  
            System.Out.Println ("没有找到你要删除的数据!");  
            Return;  
        }  
        For (int i = index; i < usedSize - 1; i++) {  
            Elem[i] = elem[i + 1];  
        }  
        UsedSize--;  
    }  
    /**  
     * removeAll 方法删除整个顺序表  
     */  
    Public void removeAll () {  
        Elem = new int[5];  
        UsedSize = 0;  
    }  
    //    判满方法  
    Private boolean isFull () {  
        Return usedSize == elem. Length;  
    }  
    //    判断顺序表的下标是否合法  
    Private void checkedAddPos (int pos) {  
        if (pos < 0 || pos > usedSize) {  
            Throw new PosIndexIllegalException ();  
        }  
    }  
    //   判断下标 pos 是否合法  
    Private boolean checkGetPos (int pos) {  
        if (pos < 0 || pos >= usedSize) {  
            Return false;  
        }  
        Return true;  
    }  
    /**  
     * 获取顺序表的个数  
     *  
     * @return 返回数组的大小  
     */  
    Public int size () {  
        Return usedSize;  
    }  
}  
Class PosIndexIllegalException extends RuntimeException {  
    Public PosIndexIllegalException () {  
    }  
    Public PosIndexIllegalException (String msg) {  
        Super (msg);  
    }  
}

🍔测试程序

我们是在外部的程序 MyArrayListTest 中进行的测试,先准备两个顺序表,然后调用 merge 方法,并把两个参数传进去,然后会返回一个顺序表,我们再继续调用我们封装的 MyArrayList 类当中的 display 方法。

Package TextReport;  
Public class MyArrayListTest {  
    Public static void main (String[] args) {  
        //准备两个顺序表(非递减的顺序表)  
        MyArrayList myArrayList 1 = new MyArrayList ();  
        MyArrayList 1.Add (1);  
        MyArrayList 1.Add (5);  
        MyArrayList 1.Add (10);  
        MyArrayList 1.Add (13);  
        MyArrayList 1.Display ();  
        ;  
        MyArrayList myArrayList 2 = new MyArrayList ();  
        MyArrayList 2.Add (6);  
        MyArrayList 2.Add (11);  
        MyArrayList 2.Add (12);  
        MyArrayList 2.Add (33);  
        MyArrayList 2.Add (44);  
        MyArrayList 2.Add (47);  
        MyArrayList 2.Add (52);  
        MyArrayList 2.Add (66);  
        MyArrayList 2.Display ();  
        ;  
        //调用 merge 方法  
        MyArrayList mergeArrayList = merge (myArrayList 1, myArrayList 2);  
        //调用 display 方法  
        MergeArrayList.Display ();  
    }  
    /**  
     * 合并两个升序的非递减顺序表,并返回新的合成的顺序表  
     *  
     * @param list 1 按值非递减顺序表一  
     * @param list 2 按值非递减顺序表二  
     * @return 返回一个新的合并了的链表  
     */  
    Public static MyArrayList merge (MyArrayList list 1, MyArrayList list 2) {  
        MyArrayList newList = new MyArrayList (50);  
        Int i = 0, j = 0;  
        While (i < list 1.Size () && j < list 2.Size ()) {  
            If (list 1. Elem[i] < list 2. Elem[j]) {  
                NewList. Elem[newList. UsedSize] = list 1. Elem[i];  
                I++;  
                NewList. UsedSize++;  
            } else {  
                NewList. Elem[newList. UsedSize] = list 2. Elem[j];  
                J++;  
                NewList. UsedSize++;  
            }  
        }  
        While (i < list 1.Size ()) {  
            NewList. Elem[newList. UsedSize] = list 1. Elem[i];  
            I++;  
            NewList. UsedSize++;  
        }  
        While (j < list 2.Size ()) {  
            NewList. Elem[newList. UsedSize] = list 2. Elem[j];  
            NewList. UsedSize++;  
            J++;  
        }  
        Return newList;  
    }  
}

🥰测试结果


💗图文并茂

该图片是合并结束之后的图示,可以形象的看清楚 i ,j,k 这三个“指针是如何“行走的”。

注意:k 下标其实是 usedSize,是顺序表中的用来表示顺序表的有效长度。


🎊视频演示

这个视频简单的演示了我当前举的这个例子是如何进行合并的过程,时常两分钟,希望可以看完,这样可以更好的理解 “如何合并两个非递减的顺序表”。

两个非递减顺序表合并视频演示


点赞+收藏+关注💕

目录
相关文章
顺序表应用5:有序顺序表归并
顺序表应用5:有序顺序表归并
|
5月前
|
算法 测试技术 C#
C++二分算法:使数组严格递增
C++二分算法:使数组严格递增
|
6天前
|
算法
顺序表应用1:多余元素删除之移位算法
顺序表应用1:多余元素删除之移位算法
|
6天前
|
算法 程序员
【算法训练-链表 五】【链表求和】:链表相加(逆序)、链表相加II(顺序)
【算法训练-链表 五】【链表求和】:链表相加(逆序)、链表相加II(顺序)
62 0
|
7月前
|
C语言
【Leetcode-1574.删除最短的子数组使剩余数组有序(C语言)】
【Leetcode-1574.删除最短的子数组使剩余数组有序(C语言)】
20 0
|
存储 机器学习/深度学习 缓存
链表和有序二叉树插入元素时真的比数组快吗?
公司有位C++标准委员会的顾问大佬,一年会有几次视频讲座,分享一些编程要点或者经验。很多时候都是C++很基础的方面,但是他的讲解视频真的很深入浅出,有时候会“打破”一些理所应当的观点,这篇文章就是让我觉得很有趣,并且意想不到的地方,在这里分享一下。
链表和有序二叉树插入元素时真的比数组快吗?
|
算法 搜索推荐 Java
Day5 数组中插入元素与插入排序
Day5 数组中插入元素与插入排序
Day5 数组中插入元素与插入排序
|
存储
把数组排成最小的数_数组中的逆序对(归并统计法)_数字在升序数组中出现的次数_丑数(剑指offer)
把数组排成最小的数_数组中的逆序对(归并统计法)_数字在升序数组中出现的次数_丑数(剑指offer)
116 0
把数组排成最小的数_数组中的逆序对(归并统计法)_数字在升序数组中出现的次数_丑数(剑指offer)