链表

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-22 02:29:29
1、判断一个单链表中是否有环 思路:给定两个指针fast和low都指向头结点,然后low每次前进一步,fast每次前进两步,如果此单链表中有环,那么fast和low一定会相遇,否则fast一定会先遇到null。实现代码如下: bool isCircle(LinkList *head){ LinkList *fast = head;//快指针 LinkList *low = head;//慢指针 while(low->next != NULL && fast->next->next != NULL) { low = low->next; fast = fast->next->next; if (low == fast) { return true; } } return false;} 现在还有个问题需要思考, 为什么如果链表有环,fast和low就一定会相遇呢? 假设单链表长度为n,且该单链表是环状的。 ① 若low和fast的起点相同,那么第i次迭代时,low指向元素(i mod n),q指向(2i mod n)。因此当i≡2i(mod n)时,fast和low相遇。而i≡2i(mod n) → (2i-i)mod n=0 → (i mod n) = 0 →当i=n时,fast和low相遇。 ② 若low和fast的起点不同,假设第i次迭代时low指向元素(i mod n)

图的创建,图的深度优先遍历和广度优先遍历

柔情痞子 提交于 2020-02-21 19:53:20
图 图的表现形式: 邻接矩阵:使用二维数组,行列表示各个顶点,使用规定的数来表示两个顶点之间是否存在边。 例如: 上面就是上面图的邻接矩阵,其中0代表无连接,1代表链接。 除了使用邻接矩阵,还可以使用邻接表表示,邻接表就是针对每一个顶点有一个链表,该链表指向了每一个可以链接的顶点。所有顶点的链表构成的数组。 JAVA构建图: // 存储图的顶点 private List < String > vertexList ; // 邻接矩阵 private int [ ] [ ] edges ; // 边的条数 private int numOfEdges ; // 标记顶点是否有被访问过 private boolean [ ] isVisited ; // 初始化一个n个顶点的图 public Graph ( int n ) { edges = new int [ n ] [ n ] ; vertexList = new ArrayList < String > ( n ) ; } /** * 添加图的边 * * @param v1 第一个顶点下标 * @param v2 第二个顶点下标 * @param weight 权值 */ public void insertEdge ( int v1 , int v2 , int weight ) { // 构建的无向图 edges [ v1

删除排序链表所有重复元素,使得每个元素只出现一次(一)

随声附和 提交于 2020-02-21 19:26:36
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。LeetCode的83题,以后题目的序号有可能会改变 示例 1: 给定链表: 1->1->2 处理结果: 1->2 示例 2: 给定链表: 1->1->2->3->3 处理结果: 1->2->3 代码如下: 原文链接:https://blog.csdn.net/if_i_were_a/article/details/89092123 public ListNode deleteDuplicates(ListNode head) {   //设置一个指向当前元素的指针   ListNode current = head;   //当链表为空或者链表中遍历到最后一个元素时,出循环   while (current != null && current.next != null) {     //如果找到当前节点和它的下一个结点的值相同,删除掉下一个结点     if (current.next.val == current.val) {       current.next = current.next.next;     } else {       //如果没有找到,当前节点后移       current = current.next;     }   }   return head; } 来源

快慢指针

有些话、适合烂在心里 提交于 2020-02-21 15:48:36
快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2,慢指针每次向前移动1次。 快慢指针的应用 判断单链表是否为循环链表 让快慢指针从链表头开始遍历,快指针向前移动两个位置,慢指针向前移动一个位置;如果快指针到达NULL,说明链表以NULL为结尾,不是循环链表。如果 快指针追上慢指针,则表示出现了循环。 fast=slow=head; while(true){ if (fast==NULL || fast->next==NULL) return false; else if (fast==slow || fast->next==slow) return true; else{ fast=fast->next->next; slow=slow->next; } 在有序链表中寻找中位数 该方法在不借助计数器变量实现寻找中位数的功能。原理是:快指针的移动速度是慢指针移动速度的2倍,因此当快指针到达链表尾时,慢指针到达中点。程序还要考虑链表结点个数的奇偶数因素,当快指针移动x次后到达表尾(1+2x),说明链表有奇数个结点,直接返回慢指针指向的数据即可。如果快指针是倒数第二个结点,说明链表结点个数是偶数,这时可以根据“规则”返回上中位数或下中位数或(上中位数+下中位数)的一半。 while (fast&&slow) { if (fast->next

剑指Offer24-反转链表

你离开我真会死。 提交于 2020-02-21 11:42:19
剑指Offer典型题整理 - 争取做最好的题解 剑指Offer24-反转链表 整理时间:2020年02月17日 本题和 LeetCode-206 相同 题目描述 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点,使用递归和迭代两种方式实现。 示例 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 限制: 0 <= 节点个数 <= 5000 题解 这是一道非常经典的题目了,递归和迭代两种实现实现方法更是能够体现基本编程素养。 😊解法1:双指针迭代法 需要使用到两个指针,指针 cur 定位原先链表的头,指针 pre 定位逆转链表的头。解决这种问题最好的方法还是画图自己分析,流程图如下: C++版本 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* reverseList(ListNode* head) { ListNode *pre = NULL; ListNode *cur = head; while (cur !=

leetcode菜狗入门 | 21. 合并两个有序链表

纵饮孤独 提交于 2020-02-21 04:29:23
合并两个有序链表 题目描述 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 输入: 1 - > 2 - > 4 , 1 - > 3 - > 4 输出: 1 - > 1 - > 2 - > 3 - > 4 - > 4 解题思路 是普遍的递归解法,主要就是要有递归的思想。链表、二叉树都是比较大的概率使用递归解法。 代码 /** * 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 ) { if ( l2 == NULL ) { return l1 ; } if ( l1 == NULL && l2 != NULL ) { return l2 ; } if ( l1 - > val < l2 - > val ) { l1 - > next = mergeTwoLists ( l1 - > next , l2 ) ; return l1 ; } else {

线性表的链式存储

痴心易碎 提交于 2020-02-20 19:26:16
线性表的链式存储 顺序存储就是数组来,好理解但插入和删除数据多就不方便,链式存储就很方便。 表长 查找 插入 注意:头插,尾插 *(自行思考一下)* /* 带头结点的插入 */ /*注意:在插入位置参数P上与课程视频有所不同,课程视频中i是序列位序(从1开始),这里P是链表结点指针,在P之前插入新结点 */ bool Insert ( List L , ElementType X , Position P ) { /* 这里默认L有头结点 */ Position tmp , pre ; /* 查找P的前一个结点 */ for ( pre = L ; pre && pre -> Next != P ; pre = pre -> Next ) ; if ( pre == NULL ) { /* P所指的结点不在L中 */ printf ( "插入位置参数错误\n" ) ; return false ; } else { /* 找到了P的前一个结点pre */ /* 在P前插入新结点 */ tmp = ( Position ) malloc ( sizeof ( struct LNode ) ) ; /* 申请、填装结点 */ tmp -> Data = X ; tmp -> Next = P ; pre -> Next = tmp ; return true ; } } 删除 /*

HashMap源码简析

痞子三分冷 提交于 2020-02-20 17:49:15
package com . example . demo . sort ; import java . io . IOException ; import java . io . InvalidObjectException ; import java . io . Serializable ; import java . lang . reflect . ParameterizedType ; import java . lang . reflect . Type ; import java . util . AbstractMap ; import java . util . Map ; import java . util . Objects ; import java . util . Set ; import java . util . AbstractSet ; import java . util . ConcurrentModificationException ; import java . util . Iterator ; import java . util . Spliterator ; import java . util . NoSuchElementException ; import java . util . Collection ;

HashMap源码详解

帅比萌擦擦* 提交于 2020-02-20 08:47:52
概述 HashMap是基于哈希表(散列表),实现Map接口的双列集合,数据结构是“链表散列”,也就是数组+链表 ,key唯一的value可以重复,允许存储null 键null 值,元素无序。 哈希表 数组:一段连续控件存储数据,指定下标的查找,时间复杂度O(1),通过给定值查找,需要遍历数组,自已对比复杂度为O(n) 二分查找插值查找,复杂度为O(logn) 线性链表:增 删除仅处理结点,时间复杂度O(1)查找需要遍历也就是O(n) 二叉树:对一颗相对平衡的有序二叉树,对其进行插入,查找,删除,平均复杂度O(logn) 哈希表:哈希表中进行添加,删除,查找等操作,性能十分之高,不考虑哈希冲突的情况下,仅需一次定位即可完成,时间复杂度为O(1)哈希表的主干就是数组 hash冲突 如果两个不同的元素,通过哈希函数得出的实际存储地址相同怎么办?也就是说,当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲突,也叫哈希碰撞。前面我们提到过,哈希函数的设计至关重要,好的哈希函数会尽可能地保证 计算简单和散列地址分布均匀,但是,我们需要清楚的是,数组是一块连续的固定长度的内存空间,再好的哈希函数也不能保证得到的存储地址绝对不发生冲突。那么哈希冲突如何解决呢?哈希冲突的解决方案有多种:开放定址法(发生冲突