合并排序

分治法-合并排序和快速排序

房东的猫 提交于 2020-03-19 12:41:37
分治法是按照以下方案工作的: 将问题的实例划分为同一个问题的几个较小的实例,最好拥有同样的规模 对这些较小的实例求解(一般使用递归方法,但在问题规模足够小的时候,有时会利用另一种算法以提高效率) 如果必要的话,合并较小问题的解,以得到原始问题的解 分治法的流程: 4.1 合并排序 合并排序是成功应用分治技术的一个完美例子(书上说的)。 对于一个需要排序的数组,合并排序把它一分为二,并对每个子数组递归排序,然后把这两个排好序的子数组合并为一个有序数组。 代码实现: /** * 合并排序 * @author xiaofeig * @since 2015.9.16 * @param array 要排序的数组 * @return 返回排好序的数组 * */ public static int[] mergeSort(int[] array){ if(array.length>1){ int[] subArray1=subArray(array,0,array.length/2); int[] subArray2=subArray(array,array.length/2,array.length); subArray1=mergeSort(subArray1); subArray2=mergeSort(subArray2); return merge(subArray1,subArray2

合并k个排序链表

十年热恋 提交于 2020-03-12 09:47:10
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6 思路: 两个两个组合,排序 使用递归 使用递归就要找截止条件(当节点为null) /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode mergeKLists ( ListNode [ ] lists ) { //当长度为0 就是没有链表 if ( lists . length == 0 ) { return null ; } //当长度为1 只有一个单链表 不用排序 直接返回 if ( lists . length == 1 ) { return lists [ 0 ] ; } //当长度为2 将这两个链表直接排序 if ( lists . length == 2 ) { return mergeTwoLists ( lists [ 0 ] , lists [ 1 ] ) ; } //将数组分成两部分 int

分治思想与归并排序

主宰稳场 提交于 2020-03-09 22:00:04
分治法 的思想: 将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些自问题,然后再合并这些自问题的解来建立原问题的解。 分支模式在每层递归时都有三个步骤: 分解 原问题为若干子问题,这些子问题是原问题的规模较小的实例。 解决 这些子问题,递归地求解各子问题。然而,若子问题的规模足够小,则直接求解。 合并 这些子问题的解成原问题的解。 归并排序 算法完全遵循分治模式。直观上其操作如下: 分解: 分解待排序的n个元素的序列成各具n/2个元素的两个子序列。 解决: 使用归并排序递归地排序两个子序列。 合并: 合并两个已排序的子序列以产生已排序的答案。 参考: 《算法导论》中文版原书第3版Page16,17 来源: https://www.cnblogs.com/drfxiaoliuzi/p/5892158.html

SSIS 连接数据

你离开我真会死。 提交于 2020-03-06 19:00:19
通常情况下,ETL方案需要同时访问两个或多个数据源,并把结果合并为单个数据流,输出到目标表中。为了向目标表中提供统一的数据结构,需要把多个数据源连接在一起。数据连接的另外一种用法,就是根据现有的数据,向目标表中添加数据,或者更新现有的数据。这种方案是把源数据与现有的数据进行比较,以便找到需要更新的数据行,或者需要添加的数据。在设计ETL方案时,连接数据可以使用SSIS的转换(Lookup和Merge Join)组件,或者直接在关系型数据库内部执行,而后者性能更高。 一,SSIS 连接 查找转换以嵌套循环(Nested Loop)的方式实现连接操作,该组件被设计为以同步方式进行连接操作,这意味着在进行转换的时候,查找转换不会阻塞数据流管道,但是,在全缓存(Full Cache)模式下,当组件加载查找数据集的内部缓存时,可能会阻塞包一段时间,阻塞时间的长短由加载查找数据集的时间来决定。 合并连接(Merge Join)转换也可以实现连接操作,通常情况下,它比查找转换更适合做连接操作,转换的性能更高。相比查找转换,合并连接对输入数据的要求更严格: 两个输入的数据必须是有序的 ; 设置连接类型 ,Merge Join支持Inner Join,Left Join和Full Join三种连接类型; 设置比较列的映射,Merge Join只支持等值连接,自动按照排序列设置比较列的映射;

1428:面试题 10.01. 合并排序的数组

梦想的初衷 提交于 2020-03-03 15:22:51
问题描述 给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。 初始化 A 和 B 的元素数量分别为 m 和 n。 示例 输入 : A = [ 1 , 2 , 3 , 0 , 0 , 0 ] , m = 3 B = [ 2 , 5 , 6 ] , n = 3 输出 : [ 1 , 2 , 2 , 3 , 5 , 6 ] 思路 我们可以遍历B,对于每个B中的元素都插入到A中合适的位置。这样的时间复杂度是O(m*n). (方法一) 我们可以把数组B接在数组A的后面,然后对整个数组A进行排序。这样的时间复杂度是O((n+m)log(n+m)).(方法二) 我们可以用一个临时的数组,设置两个指针分别指向A和B的开头元素,谁小就把谁复制到新的数组中(即比较出来的是最终的位置)。最后把临时数组的值全部复制到数组A中。这样的时间复杂度是O(n+m), 空间复杂度也是O(n+m)。(方法三) 我们方法三中用临时数组的原因是,我们设置两个指针分别指向A和B的开头元素,没有办法谁小就把谁放在最终的位置,因为这可能会使我们遗失一些值。由于我们选定的某个元素的最终位置上是有元素的,直接覆盖的话我们会丢失这个值(因为指针并未更新,如果强行更新,指针也不知道该指向哪里)。But who care? 我们可以转变思维

3.3 面试题 10.01. 合并排序的数组

六眼飞鱼酱① 提交于 2020-03-03 13:50:13
题目 给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。 初始化 A 和 B 的元素数量分别为 m 和 n。 示例 输入: A = [1,2,3,0,0,0], m = 3 B = [2,5,6], n = 3 输出: [1,2,2,3,5,6] 思路 假设A和B共有元素n个,那么目的就是有序的填慢A中的前n个空。 用end表示A中要填满区间的尾index。endA表示A中元素的尾index, endB表示B的尾index。 同时从尾部遍历A和B。end > -1为循环终止条件。 当endA等于-1时,说明A中的元素遍历完了。若B中还有元素,填充到A中。 当endB等于-1时,说明B中的已经填完了,此时直接break。 当endA和endB都不为-1时,选择大的从尾部填充。 代码 class Solution { public : void merge ( vector < int > & A , int m , vector < int > & B , int n ) { int end = m + n - 1 ; int endA = m - 1 ; int endB = n - 1 ; while ( end > - 1 ) { if ( endA == - 1 ) A [ end -- ] = B [

面试题 10.01. 合并排序的数组

扶醉桌前 提交于 2020-03-03 11:48:34
给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。 初始化 A 和 B 的元素数量分别为 m 和 n。 示例: 输入: A = [1,2,3,0,0,0], m = 3 B = [2,5,6], n = 3 输出: [1,2,2,3,5,6] 第一种方法: 直接把B数组放在A数组的缓冲空间,然后再使用sort排序 class Solution { public : void merge ( vector < int > & A , int m , vector < int > & B , int n ) { for ( int i = m ; i < m + n ; i ++ ) { A [ i ] = B [ i - m ] ; } sort ( A . begin ( ) , A . end ( ) ) ; } } ; 第二种方法: 使用两个指针,一个过渡数组。 方法1没有利用数组 A 与 B 已经被排序的性质。为了利用这一性质,我们可以使用双指针方法。这一方法将两个数组看作队列,每次从两个数组头部取出比较小的数字放到过渡数组中,最后放回A数组中。 class Solution { public : void merge ( vector < int > & A , int m , vector < int

LeetCode之23. 合并K个排序链表

时间秒杀一切 提交于 2020-02-23 03:02:31
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/merge-k-sorted-lists 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 思路:简单的说就是建立一个堆,这个堆是排序的。使用Python库 在这里插入代# Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def mergeKLists(self, lists: List[ListNode]) -> ListNode: import heapq dummy = ListNode(0) p =start head = [] for i in range(len(lists)): if lists[i] : heapq.heappush(head,(lists[i].val,i)) lists[i] = lists[i].next while head

Leetcode 23——合并K个排序链表 C++

夙愿已清 提交于 2020-02-22 05:41:23
此题的解法可以借鉴归并排序的做法,也体现了分治的思想: 首先实现一个合并两个链表的函数mergeTwoLists; 再将合并lists中所有的链表这个大问题,分解成“合并左部分的一半,再合并右边的一半,最后再进行一次合并”这样的小问题,并且这个小问题还可以继续细分下去,直到变成只需要合并两个链表,这样的步骤可以递归进行实现: /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public : ListNode * mergeTwoLists ( ListNode * l1 , ListNode * l2 ) { ListNode * ans = new ListNode ( - 1 ) ; ListNode * res = ans ; while ( l1 != NULL && l2 != NULL ) { if ( l1 - > val <= l2 - > val ) { ListNode * tmp = new ListNode ( l1 - > val ) ; ans - > next = tmp ; l1 = l1

排序之有序数组合并

谁说我不能喝 提交于 2020-02-15 03:04:10
问题描述:两个有序数组,一个长度为m,一个长度为n,需要将两个数组合并成一个数组 思路: 首先想到了二路归并,难点在于判断两路谁现被耗尽,未被耗尽的一个将会被依次添加数组 代码测试: ps:这是第一次的想法,最真实的水平 import java.util.Scanner; public class MergeSort { public static void main(String[] args) { Scanner p1 = new Scanner(System.in); System.out.println("输入第一个数组,数组长度为m=:"); int m = p1.nextInt(); int[] a = new int[m]; for(int i = 0;i < m;++i){ System.out.println("输入第"+(i+1)+"个数:"); a[i] = p1.nextInt(); } Scanner p2 = new Scanner(System.in); System.out.println("输入第二个数组,数组长度为n=:"); int n = p2.nextInt(); int[] b= new int[n]; for(int j = 0;j < n;++j){ System.out.println("输入第"+(j+1)+"个数:"); b[j