链表

单链表反转(递归和非递归) (Java)

纵饮孤独 提交于 2020-03-05 14:01:58
链表定义 class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } View Code 非递归实现很简单,只需要遍历一遍链表,在遍历过程中,把遍历的节点一次插入到头部。 public ListNode reverseList(ListNode head) { ListNode prev = null; while(head!=null){ ListNode tmp = head.next; head.next = prev; prev = head; head = tmp; } return prev; } View Code 递归实现:翻转head->为首的链表, 然后head变为尾部节点 public ListNode reverseList(ListNode head) { if(head==null||head.next ==null) return head; ListNode prev = reverseList(head.next); head.next.next = head; head.next = null; return prev; } View Code 来源: https://www.cnblogs.com/tina-smile/p/4878983.html

原生JS实现双向链表

旧街凉风 提交于 2020-03-05 14:01:35
1.前言 双向链表和单向链表的区别在于,在链表中,一个节点只有链向下一个节点的链接,而在双向链表中,链接是双向的:一个链向下一个元素,另一个链向前一个元素,如下图所示: 从图中可以看到,双向链表中,在每个节点 Node 里有 prev 属性(指向上一个节点的指针)和 next 属性(指向下一个节点的指针),并且在链表中也有 head 属性(用来存储链表第一项的引用)和 tail 属性(用来存储链表最后一项的引用)。 2.代码实现 首先,我们可以先创建一个双向链表DoublyLinkedList类: //创建一个Node辅助类,用来生成节点 class Node{ constructor(value){ this.value = value; this.next = null; this.prev = null; } } class DoublyLinkedList{ constructor(){ this.head = null; this.tail = null; this.length = 0; } append(element){ } find(value){ } insert(position,element){ } remove(value) { } removeAt(position){ } size(){ } isEmpty(){ } nextPrint() { }

C++ 单向链表反转

戏子无情 提交于 2020-03-05 14:00:18
单向链表反转,一道常见的面试题,动手实现下。 1 #include "stdafx.h" 2 #include <stdlib.h> 3 struct Node{ 4 int data; 5 Node* next; 6 }; 7 8 void print1(Node *head) 9 { 10 Node *p; 11 p=head; 12 if(head!= NULL) 13 do 14 { 15 printf("%d \n", p->data); 16 p=p->next; 17 }while(p!=NULL); 18 } 19 20 Node* ReverseList(Node* head) 21 { 22 if(head==NULL) 23 return NULL; 24 25 Node* cur=head; 26 Node* pre=NULL; 27 Node* nx=NULL; 28 while(cur->next!=NULL) 29 { 30 nx=cur->next; 31 cur->next=pre; 32 pre=cur; 33 cur=nx; 34 } 35 cur->next=pre; 36 return cur; 37 } 38 Node* init( int num) // insert from back 39 { 40 if(0 >= num) 41

反转单向链表

心已入冬 提交于 2020-03-05 13:59:51
  据说在求职面试中,经常会出反转链表难题,意思就是将 a->b->c->d->e 这样单向链表转成 e->d->c->b->a 。仔细想来这也不是非常难以解决的问题!常见的两种思路是:1.设置一个辅助指针(auxiliary pointer);2.利用递归(recursion)。在经历了无数打击之后,还是觉得先从算法,从编码开始,从而提高自己编码水平!下面是我对两种思路的程序实现,写在此,仅以此为起点,踏上程序实践的路途。 1 /* 2 * reverse single direct linklist 3 */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 7 typedef int KeyType; 8 typedef struct LNode{ 9 KeyType data; 10 struct LNode *next; 11 }*LN; 12 13 void initList(LN &L){ 14 LN tmpPtr; 15 L = (struct LNode *)malloc(sizeof(LN)); 16 L->next = NULL; 17 tmpPtr = L; 18 KeyType key; 19 printf("input elem:"); 20 while(scanf("%d",&key)){ 21 if(key==

leetcode-两数相加,链表问题

血红的双手。 提交于 2020-03-05 13:58:01
题目:给定两个非空链表来代表两个非负整数,位数按照逆序方式存储,它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807 public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode head = new ListNode(0); ListNode begin = head; int carry = 0;//特意查了一下进位的单词,还真的是carry while(l1 != null || l2 != null || carry != 0){ ListNode temp = new ListNode(0); int sum = (l1==null?0:l1.val) + (l2==null?0:l2.val) + carry;//从最低位开始,两个节点的数之和以及进上来的数字相加,carry初始为0 temp.val = sum%10;//当前节点的数值 carry = sum/10;//进位数 begin.next = temp;//指向下一节点 begin = temp;//将开始节点重置为当前的节点

链表-两数相加

元气小坏坏 提交于 2020-03-05 13:57:42
给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807 非常简单的链表合并,注意一下最后的进位也要加进去。 这题主要是代码优化,按照我以前看的那本数据结构书,我要写3个while和1个if。。。而里面的内容大同小异。。看了别人的解法后真的是心明眼亮,豁然开朗。 感觉自己花时间琢磨一下也能简化成这样,但是时间就是金钱!!偷懒就是生产力!! /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) { struct ListNode *p=l1,*q=l2; struct ListNode *head,*rear; int add,val,carry=0; while(p||q||carry>0) { add=0; if(p) {

链表相加

五迷三道 提交于 2020-03-05 13:57:13
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807 public static ListNode addTwoNumbers(ListNode l1,ListNode l2) { int len1 = getLength(l1); int len2 = getLength(l2); int c = 0; //定义虚拟头结点 ListNode dummy = new ListNode(-1); //定义标记结点 ListNode sign = dummy; //判断两链表长度,将短链表向长链表上加 if(len2>=len1){ //虚拟结点指向长链表头结点 dummy.next = l2; while(l1!=null){ int add = l1.val+l2.val+c; int t = add/10; int mod = add%10; if(t == 0){ l2.val = add; c = 0; }else{ l2.val

从尾到头打印链表

淺唱寂寞╮ 提交于 2020-03-05 13:31:17
将一个链表从尾到头打印,以数组形式输出。 方法①:正常打印链表存储在数组中,将数组反转。 struct ListNode { int val ; ListNode * next ; ListNode ( int x ) : val ( x ) , next ( NULL ) { } } ; class Solution { public : vector < vector < int >> print_List ( ListNode * head ) { vector < vector < int >> ans ; if ( head == NULL ) return ans ; ListNode * p = head ; while ( p ) { ans . push_back ( p - > val ) ; p = p - > next ; } reverse ( ans . begin ( ) , ans . end ( ) ) ; return ans ; } } ; 方法②:入栈打印 方法③:改变链表结构 来源: CSDN 作者: 2020向前冲_ 链接: https://blog.csdn.net/weixin_43086349/article/details/104670600

Java 集合小结

倖福魔咒の 提交于 2020-03-05 12:26:33
1.List 1.1 ArrayList 以数组实现。节约空间,但数组有容量限制。 超出限制时会增加50%容量,用System.arraycopy()复制到新的数组。因此最好能给出数组大小的预估值。默认第一次插入元素时创建大小为10的数组 。 按数组下标访问元素-get(i)、set(i,e) 的性能很高,这是数组的基本优势。 如果按下标插入元素、删除元素- add(i,e)、 remove(i)、remove(e),则要用System.arraycopy()来复制移动部分受影响的元素 ,性能就变差了。 越是前面的元素,修改时要移动的元素越多。直接在数组末尾加入元素-常用的add(e),删除最后一个元素则无影响。 1.2 LinkedList 以双向链表实现。链表无容量限制,但双向链表本身使用了更多空间,每插入一个元素都要构造一个额外的Node对象,也需要额外的链表指针操作。 按下标访问元素-get(i)、set(i,e) 要悲剧的部分遍历链表将指针移动到位 (如果i>数组大小的一半,会从末尾移起)。 插入、删除元素时修改前后节点的指针即可,不再需要复制移动。但还是要部分遍历链表的指针才能移动到下标所指的位置。 只有在链表两头的操作-add()、addFirst()、removeLast()或用iterator()上的remove()倒能省掉指针的移动。 Apache

数字循环右移 解题报告

我只是一个虾纸丫 提交于 2020-03-05 09:53:13
数字循环右移 题目如下: 一个数组a中存有n(>0)个整数,将每个整数循环向右移m(≥0)个位置,即将a中的数据由(a​0 a1​​ ⋯a​n−1​​ )变换为(an−m​​ ⋯a​n−1​​ a​0​​ a​1​​ ⋯a​n−m−1​​ )(最后m个数循环移至最前面的m个位置)。 我的思路: 题目明确告诉我们要将每个整数循环向右移动,所以这题可以嵌套循环,逐个移动,容易理解,但效率相对低一点。使用链表可以提高效率。解决这个问题我们需要知道用户传入数据的数量n以及移动的位数m。 方法一: 创建一个数组保存用户传入的数据,每一次循环中先将数组的最后一个数保存到临时变量里,然后逐个右移赋值,再将临时变量赋值给第一个数组元素,进行m个循环即可。 流程图如下: 方法二: 使用尾插法建立一个链表存放用户传入的数据,先连后断,先让表尾指向表头,再找到指定的位置断开并把断开后的下一个结点作为表头 核心代码如下:(建立链表部分省略) 其中m=m%n是为了减少重复循环,for循环是为了找到需要断开的结点。 至于流程图,咕wo咕bu咕hui咕hua。 来源: https://www.cnblogs.com/zxc12/p/12049360.html