leetcode启动!(╯‵□′)╯︵┻━┻
尝试改掉想到哪写哪的代码坏习惯
链表
相交链表
public class Solution {
/**
a
c(公共长度)
b
所以 链表A的长度 a + c,链表B的长度b + c
a + b + c = b + c + a
只要指针a从headA开始走,走完再回到headB
指针b从headB开始走,走完回到headA
两个指针相遇的地方一定是链表交点
*/
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pA = headA;
ListNode pB = headB;
while(pA != pB) {
pA = (pA == null) ? headB : pA.next;
pB = (pB == null) ? headA : pB.next;
}
return pA;
}
}
class Solution {
/**
设置一个null结点pre作为反转后的尾结点
curr结点一路向后遍历
因为要改变结点指向,所以需要用temp保存curr下一个结点
开写~
*/
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while(cur != null) {
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
class Solution {
/**
反转链表,和旧链表逐个元素比较
主打一个耗时耗力
*/
public boolean isPalindrome(ListNode head) {
ListNode pre = null;
ListNode cur = head;
ListNode copy = head;
ListNode old = new ListNode(head.val);
ListNode oldList = old;
while(copy != null) {
// System.out.println(copy.val);
copy = copy.next;
if(copy != null) {
ListNode temp = new ListNode(copy.val);
old.next = temp;
old = old.next;
}
}
old.next = null;
while(cur != null) {
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
ListNode newList = pre;
while(newList != null) {
if(newList.val != oldList.val) {
return false;
}
newList = newList.next;
oldList = oldList.next;
}
return true;
}
}
public class Solution {
/**
使用快慢指针
slow一次走一步,fast一次走两步
快慢指针一定会在环内相遇,记为meet点
这个时候slow从head开始走,meet从相遇点开始走,两者一定会在环入口相遇
*/
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
ListNode connect = null;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if(slow == fast) {
connect = slow;
return true;
}
}
return connect == null ? false : true;
}
}
public class Solution {
/**
原来上一题的判断写成了这一题的找环的入口
思路一样
接着上一题找到meet点
此时只要slow再次从头开始走,meet指针向后走,两者就一定会在环入口处相遇
*/
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if(slow == fast) {
ListNode meet = slow;
slow = head;
while(slow != meet) {
slow = slow.next;
meet = meet.next;
}
return slow;
}
}
return null;
}
}
class Solution {
/**
朴实无华的想法
新建一个头结点null,进行结点挑选
list1.val > list2.val ? 好,挑list2的结点来复制
list1.val <= list2.val ? 好,挑list1的结点来复制
如果list1或者list2走到头了,就直接选择不空的一连(因为已经排好序了)
需要注意的是,所有的情况用if-else分好,否则会执行出错
*/
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
ListNode p = new ListNode(-1);
ListNode res = p;
while(list1 != null || list2 != null) {
if(list1 == null) {
p.next = list2;
return res.next;
}
else if(list2 == null) {
p.next = list1;
return res.next;
}
else {
if(list1.val > list2.val) {
ListNode temp = new ListNode(list2.val);
p.next = temp;
p = p.next;
list2 = list2.next;
}
else {
ListNode temp = new ListNode(list1.val);
p.next = temp;
p = p.next;
list1 = list1.next;
}
}
}
return res.next;
}
}
两数相加
(什么破代码又臭又长 (┙>∧<)┙へ┻┻)
import java.math.BigInteger;
class Solution {
/**
朴实无华的想法,逆序想到栈道先进后出功能,使用栈保存数据
时间空间效率你是一点不考虑啊苦路西
测试用例有超出Long范围的,需要BigInteger
BigInteger b1 = new BigInteger("2020031920200319");
BigInteger b2 = new BigInteger("2020031820200318");
//加法
BigInteger add = b1.add(b2);
System.out.println(add);
//减法
BigInteger subtract = b1.subtract(b2);
System.out.println(subtract);
//乘法
BigInteger multiply = b1.multiply(b2);
System.out.println(multiply);
//除法
BigInteger divide = b1.divide(b2);
System.out.println(divide);
*/
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Stack<Integer> stack = new Stack();
int count1 = 0;
ListNode p1 = l1;
while(p1 != null) {
stack.push(p1.val);
p1 = p1.next;
count1++;
}
BigInteger sum1 = new BigInteger("0");
BigInteger base = BigInteger.TEN;
while(!stack.isEmpty()) {
int temp = stack.pop();
count1--;
BigInteger tempAsBigInteger = BigInteger.valueOf(temp);
BigInteger ten = base.pow(count1);
BigInteger mul = tempAsBigInteger.multiply(ten);
sum1 = sum1.add(mul);
}
int count2 = 0;
ListNode p2 = l2;
while(p2 != null) {
stack.push(p2.val);
count2++;
p2 = p2.next;
}
BigInteger sum2 = new BigInteger("0");
while(!stack.isEmpty()) {
int temp = stack.pop();
count2--;
BigInteger tempAsBigInteger = BigInteger.valueOf(temp);
BigInteger ten = base.pow(count2);
BigInteger mul = tempAsBigInteger.multiply(ten);
sum2 = sum2.add(mul);
}
System.out.println(sum1);
System.out.println(sum2);
BigInteger sum = new BigInteger("0");
sum = sum1.add(sum2);
System.out.println(sum);
ListNode res = new ListNode(0);
ListNode r = res;
if((sum.compareTo(BigInteger.ZERO)) == 0) {
return r;
}
while((sum.compareTo(BigInteger.ZERO)) != 0) {
BigInteger x = sum.mod(base);
// System.out.println(x);
int x1 = x.intValue();
// System.out.println(x1);
ListNode temp = new ListNode((int)x1);
res.next = temp;
res = res.next;
sum = sum.divide(base);
}
return r.next;
}
}
class Solution {
/**
快指针fast先走N布
然后慢指针slow从头开始,和fast一起走,当fast走到头了,slow在的位置就是要删除的位置
1 - 2 - 3 - 4 - null
-
2 1 0
-
- -
- -
删
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p = new ListNode(-1);
p.next = head;
ListNode res = p;
ListNode fast = p;
ListNode slow = p;
while(n > 0) {
n--;
fast = fast.next;
}
while(fast.next != null) {
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return p.next;
}
}
class Solution {
/**
-1 - 1 - 2 - 3 - 4
1 保存一下pre
-1 - 2 - 3 - 4
3 - 4 保存一下after
-1 - 2 - 1
-1 - 2 - 1 - 3 - 4
*/
public ListNode swapPairs(ListNode head) {
ListNode p = new ListNode(-1);
ListNode res = p;
p.next = head;
while(p.next != null && p.next.next != null) {
ListNode pre = p.next;
p.next = p.next.next;
ListNode after = p.next.next;
p.next.next = pre;
pre.next = after;
p = pre;
}
return res.next;
}
}
class Solution {
/**
只需要想递归最后一次
null <- 2 <- 1 3 -> 4 -> 5 -> null
2.next = reverseGroup(., k)
*/
public ListNode reverseKGroup(ListNode head, int k) {
if(head == null) {
return null;
}
ListNode a = head;
ListNode b = head;
for(int i = 0; i < k; i++) {
if(b == null) {
return head;
}
b = b.next; // 判断要在指针后移之前啊啊啊啊
}
// 一开始用的while k--, 忘了把k从0恢复
ListNode newHead = reverseKNodes(a, b);
a.next = reverseKGroup(b, k);
return newHead;
}
public ListNode reverseKNodes(ListNode a, ListNode b) {
ListNode pre = null;
ListNode cur = a;
while(cur != b) {
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
class Solution {
/**
感觉和拷贝链表没有什么区别
多了个random嘛, 用hashmap存
*/
public Node copyRandomList(Node head) {
Node h = head;
HashMap<Node, Node> map = new HashMap<>();
Node newHead = new Node(-1);
Node h1 = newHead;
while(h != null) {
Node temp = new Node(h.val);
map.put(h, temp);
newHead.next = temp;
newHead = newHead.next;
h = h.next;
}
h = head;
Node h2 = h1.next;
while(h != null) {
h2.random = map.get(h.random);
h = h.next;
h2 = h2.next;
}
return h1.next;
}
}
class Solution {
/**
朴实无华的想法
用List存链表元素,Collections.sort()进行排序,再新建一个链表
*/
public ListNode sortList(ListNode head) {
List<Integer> list = new ArrayList();
ListNode h = head;
ListNode sortedList = new ListNode(-1);
ListNode res = sortedList;
while(h != null) {
list.add(h.val);
h = h.next;
}
Collections.sort(list);
for(int i = 0; i < list.size(); i++) {
ListNode temp = new ListNode(list.get(i));
sortedList.next = temp;
sortedList = sortedList.next;
}
return res.next;
}
}
class Solution {
/**
使用最小堆
注意:lists是一个数组,是用lists.length获取长度
*/
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0) {
return null;
}
ListNode p = new ListNode(-1);
ListNode res = p;
PriorityQueue<ListNode> pq = new PriorityQueue<>(
lists.length, (a,b) -> (a.val - b.val)
);
for(ListNode head :lists) {
if(head != null) {
pq.add(head);
}
}
while(!pq.isEmpty()) {
ListNode node = pq.poll();
p.next = node;
if(node.next != null) {
pq.add(node.next);
}
p = p.next;
}
return res.next;
}
}
class LRUCache {
/**
八股问过,内存淘汰策略,删除存活时间最久的key
allkesy-lru
*/
int cap;
LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>();
public LRUCache(int capacity) {
this.cap = capacity;
}
public int get(int key) {
if(!cache.containsKey(key)) {
return -1;
}
makeRecently(key);
return cache.get(key);
}
public void put(int key, int val) {
if(cache.containsKey(key)) {
cache.put(key, val);
makeRecently(key);
return;
}
if(cache.size() >= this.cap) {
int oldestKey = cache.keySet().iterator().next();
cache.remove(oldestKey);
}
cache.put(key, val);
}
private void makeRecently(int key) {
int val = cache.get(key);
cache.remove(key);
cache.put(key, val);
}
}