1.找出两个链表的交点
160.intersection-of-two-linked-lists
Leetcode
找两个链表的相交节点,简单的很,直接暴力解法,双重遍历就完事了。
时间复杂度O(n^2),这种解法属实憨逼,面试要是上来就这个解法你就已经结束了。
//2020年8月17日
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null){
return null;
}
ListNode a = headA;
ListNode b = headB;
while(headA!=null){
while(headB!=null){
if(headA == headB){
return headA;
}
headB = headB.next;
}
headA = headA.next;
headB = b;
}
return null;
}
}经过一番思考后,有了如下代码。
假设两个链表有相交的话,那么定有广义上的一个长链表,一个短链表,将指针置为两个链表的头部,当短链表遍历完,长链表没遍历完的时候,指向短链表的指针重新指向长链表的头部,如此往复循环。
这个是个什么原理呢?
我们将下图中(1 2节点段)称为A,(3 4 5节点段)称为 C, (8 6 7节点段)称为B,那么就有
A + C + B = B + C + A
也就是上文提到的短链表遍历完从另一个链表头开始遍历的原因,这么下去,总有一天,两个指针会相遇的。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a = headA,b=headB;
while(a != b){
a = (a == null) ? headB : a.next;
b = (b == null) ? headA : b.next;
}
return a;
}
}
2.删除排序链表中的重复元素
83.remove-duplicates-from-sorted-list
Leetcode
看到这题的第一想法还是遍历,可能这就是笨比吧,下面解法的大致思路如下:
设置两个指针,一个旗标:
a指针指向head节点,b指针为a指针的next节点,如果b和a指针指向的节点的值相同,则a.next = b.next
否则a指针继续往前走。
//2020年8月18日
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode a = head;
int flag = 0;
while(a!=null){
ListNode b = a.next;
if(b == null) flag=0;
while(b!=null){
if(a.val == b.val){
a.next = b.next;
flag = 1;
}else{
flag = 0;
}
break;
}
if(flag != 1){
a = a.next;
}
}
return head;
}
}由于这个写法实在是太笨了,看了下别人的解法:
首先将问题简化,当链表为null或[1]的时候,直接返回head
当链表长度为2及以上的时候,我们就要获取当前节点的next节点与当前节点进行比较,相等的话就取后面的节点。
写的好乱,md
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) return head;
head.next = deleteDuplicates(head.next);
return head.val == head.next.val ? head.next : head;
}3.删除链表的倒数第N个节点
19.remove-nth-node-from-end-of-list
Leetcode
我一开始想的是快慢指针的方法,一个快指针先走n步,然后两个指针再同时走,直到快指针的next为空;
这样慢指针的next就是我们要删除的节点,这样做确实可以通过一些样例,但是遇到就一个节点或者[1,2,3,4] 删除倒数第4个节点这样的,这个方法就不行了。
经过一番思考和搜索,我找到了一个设置预先指针的方法,预先指针p的next指向head节点,快指针与慢指针同时从预先节点出发,最后返回p.next,这样就避免了要删除的节点就是慢指针指向的那个节点的情况。
//2020年8月19日
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode c = new ListNode(-1);
c.next = head;
ListNode a = c,b = c;
while(n != 0){
b = b.next;
n--;
}
while(b.next != null){
a = a.next;
b = b.next;
}
a.next = a.next.next;
return c.next;
}
}4.两两交换链表中的节点
24.swap-nodes-in-pairs
Leetcode
//2020年8月20日
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null) return head;
ListNode preNode = new ListNode(-1);
preNode.next = head;
ListNode c = preNode;
while(preNode.next != null && preNode.next.next != null){
ListNode a = preNode.next;
ListNode b = a.next;
preNode.next = b;
a.next = b.next;
b.next = a;
preNode = preNode.next.next;
}
return c.next;
}
}5.链表求和
445.add-two-numbers-ii
Leetcode
//2020年8月28日
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Stack<Integer> s1 = new Stack();
Stack<Integer> s2 = new Stack();
Stack<Integer> res = new Stack();
ListNode p1 = l1,p2 = l2;
ListNode head = new ListNode(-1);
int mul = 0;
while(p1!=null){
s1.push(p1.val);
p1 = p1.next;
}
while(p2!=null){
s2.push(p2.val);
p2 = p2.next;
}
while(!s1.isEmpty() || !s2.isEmpty() || mul!=0){
int x = s1.isEmpty() ? 0 : s1.pop();
int y = s2.isEmpty() ? 0 : s2.pop();
int sum = x + y + mul;
ListNode node = new ListNode(sum % 10);
node.next = head.next;
head.next = node;
mul = sum / 10;
}
return head.next;
}
}6.回文链表
- Palindrome Linked List
Leetcode
不知道为啥,我总是能想出来这种拉跨的解法。
将链表中的值放到数组中,然后在数组的首尾设置指针,比较两个指针的值是否相等
但题中提出要求说:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
说实话,O(1)空间复杂度我觉着是可以做到的,大概也是用两个指针这样的,但是具体思路嘛....
参考了cyc的思路,解法应该是这样的:将链表对半切开,将后边一半反转,依次比较是否相等
这里就涉及到了三个操作,切开,反转,比较相等
把这个解放到后面了
//2020年9月1日
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null) return true;
ListNode a = head;
ArrayList<Integer> arr = new ArrayList();
while(a != null){
arr.add(a.val);
a = a.next;
}
Object[] newArr = arr.toArray();
int len = newArr.length;
for(int i=0,j=len-1;i<j;i++,j--){
if((int)newArr[i] == (int)newArr[j]){
}else{
return false;
}
}
return true;
}
}public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) return true;
ListNode slow = head, fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
if (fast != null) slow = slow.next; // 偶数节点,让 slow 指向下一个节点
cut(head, slow); // 切成两个链表
return isEqual(head, reverse(slow));
}
//切开
private void cut(ListNode head, ListNode cutNode) {
while (head.next != cutNode) {
head = head.next;
}
head.next = null;
}
//反转
private ListNode reverse(ListNode head) {
ListNode newHead = null;
while (head != null) {
ListNode nextNode = head.next;
head.next = newHead;
newHead = head;
head = nextNode;
}
return newHead;
}
//相等否
private boolean isEqual(ListNode l1, ListNode l2) {
while (l1 != null && l2 != null) {
if (l1.val != l2.val) return false;
l1 = l1.next;
l2 = l2.next;
}
return true;
}7.分隔链表
- Split Linked List in Parts
Leetcode
今天就先不写解析了,看剧了,半泽直树2第七集
//2020年9月2日
class Solution {
public ListNode[] splitListToParts(ListNode root, int k) {
int len = 0;
ListNode countForList = root;
while(countForList != null){
len++;
countForList = countForList.next;
}
int group = len / k;
int mod = len % k;
ListNode[] result = new ListNode[k];
ListNode now = root;
for(int i=0;now!=null && i<k;i++){
result[i] = now;
int curSize = group + (mod-- > 0 ? 1 : 0);
for(int j = 0; j < curSize - 1;j++){
now = now.next;
}
ListNode next = now.next;
now.next = null;
now = next;
}
return result;
}
}8.链表元素按奇偶聚集
- Odd Even Linked List (Medium)
Leetcode
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
在不使用额外空间的情况下,使用双指针法构造两个链表(一个奇链表,一个偶链表),最后再将两个链表合并到一起。
大致的思路如下图:
最后再将奇链表和偶链表连接起来
odd.next = evenHead;
//2020年9月8日
class Solution {
public ListNode oddEvenList(ListNode head) {
if(head == null) return null;
ListNode odd = head,even = head.next,evenHead = even;
while(even != null && even.next != null){
odd.next = odd.next.next;
odd = odd.next;
even.next = even.next.next;
even = even.next;
}
odd.next = evenHead;
return head;
}
}
京公网安备 11010502036488号