一、今日练习题目:
给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。第一个节点的索引被认为是 奇数 , 第二个节点的索引为 偶数 ,以此类推。
请注意,偶数组和奇数组内部的相对顺序应该与输入时保持一致。你必须在 O(1) 的额外空间复杂度和 O(n) 的时间复杂度下解决这个问题。
给你一个头结点为 head 的单链表和一个整数 k ,请你设计一个算法将链表分隔为 k 个连续的部分。每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。这 k 个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。返回一个由上述 k 部分组成的数组。
给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。请你返回该链表所表示数字的 十进制值 。
**输入:**head = [1,0,1] **输出:**5 **解释:**二进制数 (101) 转化为十进制数 (5)
请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。题目数据保证需要删除的节点 不是末尾节点 。
**输入:**head = [4,5,1,9], node = 5 输出:[4,1,9] **解释:**指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9
给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。
给定一个长度为 n 的链表 head。对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。返回一个整数数组 answer ,其中 answer[i] 是第 i 个节点( 从1开始 )的下一个更大的节点的值。如果第 i 个节点没有下一个更大的节点,设置 answer[i] = 0 。
**输入:**head = [2,1,5]
输出:[5,5,0]
二、源码分析
题目1:328. 奇偶链表
/**
* 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 oddEvenList(ListNode head) {
if (head == null) return head;
ListNode evenHead = head.next;
ListNode odd = head, even = evenHead;
while (even != null && even.next != null) {
odd.next = even.next;
odd = odd.next;
even.next = odd.next;
even = even.next;
}
odd.next = evenHead;
return head;
}
}
奇偶指针循环链表,奇数指针不断串连奇数节点,偶数指针不断串连偶数节点,最后奇数指针的结尾连接偶数节点的开始
题目2:725. 分隔链表
/**
* 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[] splitListToParts(ListNode head, int k) {
int cnt = 0;
ListNode p = head;
int len = 0;
while (p!=null) {
p = p.next;
len++;
}
int per = len/k; // 计算每个数组的长度
if (per == 0) per=1; // per可能为0,那样就每个长度设为1,后面的数组就是空
int n = len - per*k; // 多出来的长度,要均分给前面
p = head;
ListNode[] ans = new ListNode[k];
for (int i = 0; i<k&&p!=null; i++) {
ans[i] = p;
for(int j=0;j<per-1;j++){p=p.next;}//使用per-1是为了让p停留在每个部分的最后一个节点,方便后面的'断尾操作'
if(n>0){n--;p=p.next;}//n>0的话就要均分,让p后移
if(p!=null){ //断尾操作,然后后移
ListNode temp=p.next;
p.next=null;
p=temp;
}
}
return ans;
}
}
题目3:1290. 二进制链表转整数
/**
* 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; }
* }
*/
/**
* 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 int getDecimalValue(ListNode head) {
ListNode curr = reverse(head);
int result = 0;
int pow = 0;
while (curr != null) {
if (curr.val != 0) {
result += Math.pow(2, pow);
}
pow++;
curr = curr.next;
}
return result;
}
private ListNode reverse(ListNode head) {
ListNode prev = null;
ListNode curr = head;
ListNode next = null;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
}
先翻转链表,然后从头取低位开始转换十进制
题目4:237. 删除链表中的节点
public void deleteNode(ListNode node) {
node.val=node.next.val;
node.next=node.next.next;
}
将 node 的节点值修改为_node_.next 的节点的值,然后删除node.next即可
题目5:剑指 Offer II 024. 反转链表
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr!=null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
}
题目6:1019. 链表中的下一个更大节点
class Solution {
public int[] nextLargerNodes(ListNode head) {
// 把单链表转化成数组,方便通过索引访问
ArrayList<Integer> nums = new ArrayList<>();
for (ListNode p = head; p != null; p = p.next) {
nums.add(p.val);
}
// 存放答案的数组
int[] res = new int[nums.size()];
Stack<Integer> stk = new Stack<>();
// 单调栈模板,求下一个更大元素,从后往前遍历
for (int i = nums.size() - 1; i >= 0; i--) {
while (!stk.isEmpty() && stk.peek() <= nums.get(i)) {
stk.pop();
}
// 本题要求没有下一个更大元素时返回 0
res[i] = stk.isEmpty() ? 0 : stk.peek();
stk.push(nums.get(i));
}
return res;
}
}
这道题输入的是一条单链表,我们把它转化成数组,方便用索引访问即可直接使用单调栈的思路