链表

HashMap在Java1.7与1.8中的区别

风流意气都作罢 提交于 2020-04-06 00:24:23
基于 JDK1.7.0_80 与 JDK1.8.0_66 做的分析 JDK1.7中 使用一个Entry数组来存储数据,用key的hashcode取模来决定key会被放到数组里的位置,如果hashcode相同,或者hashcode取模后的结果相同(hash collision),那么这些key会被定位到Entry数组的同一个格子里,这些key会形成一个链表。 在hashcode特别差的情况下,比方说所有key的hashcode都相同,这个链表可能会很长,那么put/get操作都可能需要遍历这个链表 也就是说时间复杂度在最差情况下会退化到O(n) JDK1.8中 使用一个Node数组来存储数据,但这个Node可能是链表结构,也可能是红黑树结构 如果插入的key的hashcode相同,那么这些key也会被定位到Node数组的同一个格子里。 如果同一个格子里的key不超过8个,使用链表结构存储。 如果超过了8个,那么会调用treeifyBin函数,将链表转换为红黑树。 那么即使hashcode完全相同,由于红黑树的特点,查找某个特定元素,也只需要O(log n)的开销 也就是说put/get的操作的时间复杂度最差只有O(log n) 听起来挺不错,但是真正想要利用JDK1.8的好处,有一个限制: key的对象,必须 正确的实现了Compare接口 如果没有实现Compare接口

两个链表的第一个公共结点

夙愿已清 提交于 2020-04-06 00:15:10
题目:输入两个链表,找出它们的第一个公共结点。 链表结点定义如下: struct ListNode { int m_nKey; ListNode *m_pNext; }; 解决办法 :首先遍历两个链表得到它们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多几个结点。在第二次遍历的时候,在较长的链表上先走若干步,接着再同时在两个链表上遍历,找到的第一个相同的结点就是它们的第一个公共结点。 ListNode *FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2) { //得到两个链表的长度 unsigned int nLength1 = GetListLength(pHead1); unsigned int nLength2 = GetListLength(pHead2); int nLengthDif = nLength1 - nLength2; ListNode *pListHeadLong = pHead1; ListNode *pListHeadShort = pHead2; if(nLength2 > nLength1) { pListHeadLong = pHead2; pListHeadShort = pHead1; nLengthDif = nLength2 - nLength1; } /

两个链表的第一个公共结点

孤街醉人 提交于 2020-04-05 23:43:14
题目:输入两个链表,找出它们的第一个公共结点。 O(m+n) 思路:首先遍历两个链表得到它们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多几个结点。在第二次遍历的时候,在较长的链表上先走若干步,接着再同时在两个链表上遍历,找到的第一个相同的结点就是它们的第一个公共结点。 1 struct ListNode 2 { 3 int val; 4 ListNode * next; 5 }; 6 7 int GetListLength( ListNode * head ) 8 { 9 int length = 0; 10 ListNode *tmp = head; 11 while( !tmp ) 12 { 13 ++length; 14 tmp = tmp->next; 15 } 16 return length; 17 } 18 19 ListNode * FindFirstCommonNode( ListNode * head1, ListNode * head2 ) 20 { 21 ListNode * result = NULL; 22 23 if( head1 == NULL || head2 == NULL ) 24 { 25 return result; 26 } 27 28 int Lhead1 = GetListLength( head1 ); 29 int

单链表是否有环和两个链表是否有公共节点问题

痴心易碎 提交于 2020-04-05 22:04:32
1、单链表是否有环 题目描述 :有一个单链表,其中可能有一个环,也就是某个节点的next指向的是链表中在它之前的节点,这样在链表的尾部形成一环。问题: 1、 如何判断一个链表是不是这类链表 ? 2、 如果链表为存在环,如何找到环的入口点 ? 一、判断链表是否存在环 设置两个指针(fast, slow),初始值都指向头,slow每次前进一步,fast每次前进二步,如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。(当然,fast先行头到尾部为NULL,则为无环链表)。 1: boolean isExsitLoop() { 2: Node<T> slow = head; 3: Node<T> fast = head; 4: 5: while (fast != null && fast.next != null) { 6: slow = slow.next; 7: fast = fast.next.next; 8: 9: if (slow == fast) 10: return true; 11: } 12: return false; 13: } 二、找到环的入口点 当fast若与slow相遇时,slow肯定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈)

编程判断两个链表是否相交

家住魔仙堡 提交于 2020-04-05 19:59:37
题目:给出两个单向链表的头指针,比如h1,h2,判断这两个链表是否相交。(均不带环) 解法一:先判断第一个链表的每个节点是否在第二个链表中。复杂度O(Length(h1)*Length(h2)),显然不可以。 解法二:利用计数的方法。如何,两个链表相交的话,记他们含有相同的节点,相同的节点就有相同的地址,一个简单的方法是对第一个链表的节点地址进行hash排序,简历hash表,然后针对第二个标的每一个节点的地址查询hash表,如果他在hash表中出现,那么说明第二个链表和第一个链表有共同的节点。时间复杂度O(Length(h1)+Length(h2)),时间复杂度还不错,但增加了O(Length(h1))的空间复杂度。 解法三:转化为另一已知问题。由于没有环,所以我们把两个链表连在一起,把h2的表头接在h1的表尾,如果h1,与h2有交点的话,必然形成环,而h2的头结点一定在环里,只要从h2的开头开始,一次遍历,如果回到h2,则两个链表相交。当然,个人认为这个方法虽然复杂度低了,但是不好,因为它不能让我们得知哪些是交点。 解法四:抓住要点。如果两个链表相交,那么从第一个相交的点之后,两个链表的之后节点都相同。即最后一个节点是相同的,那么解决办法是先遍历第一个链表,记住最后一个节点,其次遍历第二个链表到最后一个链表,看是最后两个节点是否相同。编程之美上说这个方法比解法三更胜一筹

java面试基础篇-List

Deadly 提交于 2020-04-05 18:00:41
一.ArrayList:   底层为数组实现,线程不安全,查询,修改快,增加删除慢, 数据结构:数组以0为下标依次连续进行存储   数组查询元素:根据下标查询就行   数组增加元素:如果需要给index为10的位置添加,则从index为11的位置开始右移 数组删除元素:如果需要删除index为10的位置,则从index为11的位置开始左移 线程: 如果判断线程安不安全只需要了解到是否进行加锁,如果没有加锁的话,多个线程操作同一个对象时就会出现线程不安全的情况. 源码: 1.new一个arraylist,调用add方法 2.查看add方法的源码可以看出,并没有任何加锁操作,这就是线程不安全的 ,这里首先会确认数组的容量,对其进行增加,并将新的元素加入到数组中 使用场景:查询 修改多 二.LikedList:   底层为链表实现,线程不安全,查询修改慢,增加删除快 数据结构:链表的每个元素都存储了下一个元素的地址,从而使一系列的随机的内存地址串在了一起,只要有足够的内存空间,就可以为链表分配内存   链表查:当同时读取所有元素时,链表的效率很高,读第一个,读第二个,以此类推。如果需要找到某个节点时,就需要遍历整个节点,才可以找到需要的元素   链表增加元素:只需要修改它前面的那个元素指针指向的地址即可   链表删除元素:只需要将前一个元素指针指向的地址更改即可 线程:

LeetCode.24|两两交换链表中的节点

别等时光非礼了梦想. 提交于 2020-04-05 17:46:27
""" https://leetcode-cn.com/problems/swap-nodes-in-pairs/solution/liang-liang-jiao-huan-lian-biao-zhong-de-jie-di-19/ 思路:分为递归和迭代两种 方法I:递归 1.出口:当输入参数head=None或head.next=None,没有可交换,返回head并退出 2.定义此节点head对应的节点nextLN 3.1 head.next指向nextLN的后一节点 3.2 原nextLN的后一节点与它匹配节点进行递归交换 4.nextLN.next指向新节点head,完成当前节点交换 5.最后的nextLN为新链表头 方法II:迭代->交换链表需要用到3个指针:curLN,nextLN,prevLN来进行串连 1.定义dummyLN的listnode,并将其定义为prevLN 2.定义需要交换listnode,curLN=输入head;nextLN=head.next 3.交换,需要注意涉及4个链表结点 prevLN.next->nextLN curLN.next->nextLN.next nextLN.next->curLN 4.重新定义prevLN和head,下次进行交换 注意:迭代法需要一个dummy来记录head的位置保持不变 """ class Solution:

集合和映射(Set And Map)

牧云@^-^@ 提交于 2020-04-05 15:36:39
目录 集合 Set 基于二分搜索树实现集合 基于链表实现集合 集合的时间复杂度分析 映射 Map 基于链表实现映射 基于二分搜索树实现映射 映射的时间复杂度分析 leetcode上关于集合和映射的问题 集合 Set   Set是一种新的数据结构,类似于数组,但是不能添加重复的元素,基于Set集合的这个特性,我们可以使用Set集合进行客户统计和词汇统计等,集合中常用的方法如下: public interface Set<E> { void add(E e); //添加元素e,不能添加重复元素 boolean contains(E e); //当前集合中是否包含元素e void remove(E e); //删除元素e int getSize(); //获取当前集合中元素的个数 boolean isEmpty(); //判断当前集合是否为空 } 基于二分搜索树实现集合   现在让我们基于我们上章实现的二分搜索树,来实现集合中的常用操作,若你对二分搜索树还不了解,你可以先看我的上一篇文章: 二分搜索树(Binary Search Tree) 进行学习,基于二分搜索树实现的集合代码实现如下: public class BSTSet<E extends Comparable<E>> implements Set<E> { //基于二分搜索树实现集合 private BST<E> bst;

p80 链表加一(leetcode 369)

喜你入骨 提交于 2020-04-04 17:50:45
一:解题思路 采用一个虚拟的头节点maybe,同时用另外一个节点notNine指向maybe。然后考虑的情况和上道题数组加一基本上是一样的。Time:O(n),Space:O(1) 二:完整代码示例 (C++版和Java版) C++: class Solution { public: ListNode * plusOne(ListNode * head) { ListNode* mayBe = new ListNode(0); ListNode* notNine = mayBe; mayBe->next = head; for (ListNode* p = head; p != NULL; p = p->next) if (p->val != 9) notNine = p; notNine->val += 1; for (ListNode* p = notNine->next; p != NULL; p = p->next) p->val = 0; if (mayBe == notNine) return mayBe; else return head; } }; Java: public class Solution { public ListNode plusOne(ListNode head) { ListNode maybe=new ListNode(0);

203. 移除链表元素

老子叫甜甜 提交于 2020-04-04 16:43:06
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution 10 { 11 public: 12 ListNode* removeElements(ListNode* head, int val) 13 { 14 ListNode* dummy = new ListNode(-1); 15 ListNode* pre = dummy; 16 while(head) 17 { 18 if(head->val != val) 19 { 20 pre->next = head; 21 pre = pre->next; 22 } 23 head = head->next; 24 } 25 pre->next = NULL;//必须加 26 return dummy->next; 27 28 } 29 }; 来源: https://www.cnblogs.com/yuhong1103/p/12632042.html