阅读 156

算法一 链表(Java实现)

1、LeetCode206反转链表

思路:依次遍历链表节点,每遍历一个节点即逆置一个节点

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;//数据域  *     ListNode next;//指针域  *     ListNode() {}  *     ListNode(int val) { this .val = val; }  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }//构造函数  * }  */ class Solution {     public ListNode reverseList(ListNode head) {         ListNode pre = null;//指向新链表头节点的指针         ListNode cur = head;         while (cur != null) {             ListNode nextTemp = cur.next;//备份cur.next             cur.next = pre;//更新cur.next             pre = cur;//移动pre             cur = nextTemp;//遍历链表         }         return pre;//返回新链表头节点     } } 复制代码

2、LeetCode92反转链表 II

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode() {}  *     ListNode(int val) { this.val = val; }  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }  * }  */ class Solution {     public ListNode reverseBetween(ListNode head, int left, int right) {         int len = right-left+1;//计算需要逆置的节点个数         ListNode pre_head = null;//初始化开始逆置的节点的前驱         ListNode result = head;//最终转换后的链表头节点,非特殊情况即为head         while(head!=null && --left!=0){//将head向前移动left-1个位置             pre_head = head;//记录head的前驱             head = head.next;         }         ListNode modify_list_tail = head;//将modify_list_tail指向当前的head,即逆置后的链表尾         ListNode new_head = null;         while(head!=null && len!=0){//逆置len个节点             ListNode nextTemp = head.next;             head.next = new_head;             new_head = head;             head = nextTemp;             len--;         }         modify_list_tail.next = head;//连接逆置后的链表尾与逆置段的后一个节点         if(pre_head!=null){//不是从第一个节点开始逆置             pre_head.next = new_head;//将逆置链表开始的节点前驱与逆置后的头节点连接         } else{             result = new_head;//从第一个节点开始逆置,结果即为逆置后的头节点         }         return result;     } } 复制代码

3、LeetCode160相交链表

思路:1.计算headA、headB链表长度,较长的链表多出的长度

2.将较长链表的指针移动到和较短链表指针对齐的位置

3.headA和headB同时移动,当两指针指向同一个节点时,即找到

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode(int x) {  *         val = x;  *         next = null;  *     }  * }  */ public class Solution {     int get_list_length(ListNode head){//遍历链表,计算链表长度         int len = 0;         while(head != null){             len++;             head = head.next;         }         return len;     }     ListNode forward_long_list(int long_len,int short_len,ListNode head){         int delta = long_len-short_len;         while(head != null && delta != 0){             head = head.next;//将指针向前移动至多出节点个数后面的位置             delta--;         }         return head;     }     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {         int list_A_len = get_list_length(headA);         int list_B_len = get_list_length(headB);//求两个链表长度         if(list_A_len > list_B_len){             headA = forward_long_list(list_A_len,list_B_len,headA);//如果链表A长,移动headA到对应位置         }else{             headB = forward_long_list(list_B_len,list_A_len,headB);//如果链表B长,移动headB到对应位置         }         while(headA != null&&headB != null){             if(headA == headB){//当两指针指向同一个节点时,说明找到                 return headA;             }             headA = headA.next;             headB = headB.next;         }         return null;     } } 复制代码

LeetCode题解

public class Solution {     public ListNode getIntersectionNode(ListNode headA, ListNode headB) {         /**         定义两个指针, 第一轮让两个到达末尾的节点指向另一个链表的头部, 最后如果相遇则为交点(在第一轮移动中恰好抹除了长度差)         两个指针等于移动了相同的距离, 有交点就返回, 无交点就是各走了两条指针的长度         **/         if(headA == null || headB == null) return null;         ListNode pA = headA, pB = headB;         // 在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头, 而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null         while(pA != pB) {             pA = pA == null ? headB : pA.next;             pB = pB == null ? headA : pB.next;         }         return pA;     } } 复制代码

4、LeetCode142环形链表 II

思路:快慢指针赛跑

两指针速度一样,相遇时即为环的起点

/**  * Definition for singly-linked list.  * class ListNode {  *     int val;  *     ListNode next;  *     ListNode(int x) {  *         val = x;  *         next = null;  *     }  * }  */ public class Solution {     public ListNode detectCycle(ListNode head) {         ListNode slow = head, fast = head;         ListNode meet = null;//相遇的节点         while(fast != null){             slow = slow.next;             fast = fast.next;//slow和fast各先走一步                    if (fast == null) {                 return null;//如果fast遇到链表尾,则返回null             }             fast = fast.next;//fast再走一步             if (fast == slow){                 meet = fast;//fast与slow相遇,记录相遇位置                 break;             }         }         if (meet == null) {             return null;//如果没有相遇,则证明无环         }         while (fast != null && meet != null) {             if(head == meet){//当他们相遇,说明遇到环的起始位置                 return head;             }             head = head.next;//head与meet每次走一步             meet = meet.next;         }         return null;     } } 复制代码

5、LeetCode86分隔链表

思路:巧用临时头节点

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode() {}  *     ListNode(int val) { this.val = val; }  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }  * }  */ class Solution {     public ListNode partition(ListNode head, int x) {         ListNode less_head = new ListNode(0);         ListNode more_head = new ListNode(0);//设置两个临时的头节点         ListNode less_ptr = less_head,more_ptr = more_head;//对应指针指向这两个头节点         while(head != null){             if(head.val < x){//如果节点值小于x,则将该节点插入less_ptr后                 less_ptr.next = head;                 less_ptr = head;//链接完成后,less_ptr向后移动,指向head             }else{//否则将该节点插入more_ptr后                 more_ptr.next = head;                 more_ptr = head;             }             head = head.next;//遍历链表         }         less_ptr.next = more_head.next;//将less链表尾,与more链表头相连         more_ptr.next = null;//将more_ptr即链表尾节点next置空         return less_head.next;//less_head的next节点即为新链表头节点,返回     } } 复制代码

6、LeetCode138复制带随机指针的链表

深度拷贝:构造生成一个完全新的链表,即使将原链表毁坏,新链表可独立使用

c++:向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。

/* // Definition for a Node. class Node {     int val;     Node next;     Node random;//带有随机指针的链表节点     public Node(int val) {         this.val = val;         this.next = null;         this.random = null;     } } */ class Solution {     public Node copyRandomList(Node head) {         HashMap<Node,Integer> node_map = new HashMap<>();//地址到节点位置的map         List<Node> node_vec = new ArrayList<>();//使用vector根据存储节点位置访问地址         Node ptr = head;         int i = 0;         if(head==null) return null;         while(ptr != null){//将新链表节点push入node_vec,生成了新链表节点位置到地址的map             node_vec.add(new Node(ptr.val));             node_map.put(ptr,i);//记录原始链表地址至节点位置的node_map             ptr = ptr.next;//遍历原始链表             i++;//i记录节点位置         }         node_vec.get(0);         ptr = head;         i = 0;         while(ptr != null){//再次遍历原始链表,连接新链表的next指针、random指针             if(i+1>=node_vec.size()){                 node_vec.get(i).next = null;             }else{                 node_vec.get(i).next = node_vec.get(i+1);//连接新链表next指针             }             if(ptr.random != null){                 int id = node_map.get(ptr.random);//根据node_map确认                 node_vec.get(i).random = node_vec.get(id);//原链表random指针指向的位置即id             }             ptr = ptr.next;//连接新链表random指针             i++;         }         return node_vec.get(0);     } } 复制代码

7、LeetCode21合并两个有序链表

思路:比较l1和l2指向的节点,将较小的节点插入到pre指针后,并向前移动较小节点对应的指针。

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode() {}  *     ListNode(int val) { this.val = val; }  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }  * }  */ class Solution {     public ListNode mergeTwoLists(ListNode l1, ListNode l2) {         ListNode temp_head = new ListNode(0);//设置临时头节点temp_head         ListNode pre = temp_head;//使用pre指针指向temp_head         while(l1 != null&&l2 != null){             if(l1.val < l2.val){                 pre.next = l1;                 l1 = l1.next;             }else{                 pre.next = l2;                 l2 = l2.next;             }             pre = pre.next;//pre指向新连接的节点         }         if(l1 != null){             pre.next = l1;         }         if(l2 != null){             pre.next = l2;         }         return temp_head.next;     } } 复制代码

8、LeetCode23合并K个升序链表

思路:对k个链表进行分治,两两进行合并

/**  * Definition for singly-linked list.  * public class ListNode {  *     int val;  *     ListNode next;  *     ListNode() {}  *     ListNode(int val) { this.val = val; }  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }  * }  */ class Solution {     public ListNode mergeKLists(ListNode[] lists) {         if(lists.length == 0)             return null;         if(lists.length == 1)             return lists[0];         if(lists.length == 2){            return mergeTwoLists(lists[0],lists[1]);         }         int mid = lists.length/2;         ListNode[] sub1_lists = new ListNode[mid];         ListNode[] sub2_lists = new ListNode[lists.length-mid];//拆分lists为两个子lists         for(int i = 0; i < mid; i++){             sub1_lists[i] = lists[i];         }         for(int i = mid,j = 0; i < lists.length; i++,j++){             sub2_lists[j] = lists[i];         }         return mergeTwoLists(mergeKLists(sub1_lists),mergeKLists(sub2_lists));//分治处理     }     public ListNode mergeTwoLists(ListNode l1, ListNode l2) {         if (l1 == null) return l2;         if (l2 == null) return l1;         ListNode head = null;         if (l1.val <= l2.val){             head = l1;             head.next = mergeTwoLists(l1.next, l2);         } else {             head = l2;             head.next = mergeTwoLists(l1, l2.next);         }         return head;     } }


作者:zust_Isabella
链接:https://juejin.cn/post/6987751828691615752


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐