力扣爆刷第103天之CodeTop100五连刷1-5
文章目录
- 力扣爆刷第103天之CodeTop100五连刷1-5
- 一、3. 无重复字符的最长子串
- 二、206. 反转链表
- 三、146. LRU 缓存
- 四、215. 数组中的第K个最大元素
- 五、25. K 个一组翻转链表
一、3. 无重复字符的最长子串
题目链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/
思路:求最长无重复子串,典型滑动窗口,用set记录是否重复,无重扩大窗口,有重缩小窗口,每次添加元素后更新最大值。
class Solution {
public int lengthOfLongestSubstring(String s) {
int max = 0;
Set<Character> set = new HashSet<>();
int slow = 0;
for(int i = 0; i < s.length(); i++) {
while(set.contains(s.charAt(i))) {
set.remove(s.charAt(slow));
slow++;
}
set.add(s.charAt(i));
max = Math.max(max, set.size());
}
return max;
}
}
二、206. 反转链表
题目链接:https://leetcode.cn/problems/reverse-linked-list/description/
思路:翻转链表采用头插法,一个指针指向虚拟头结点保持不动,另一个指针每次向后走,进行头插。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode root = new ListNode();
ListNode p = head;
while(p != null) {
ListNode pre = p.next;
p.next = root.next;
root.next = p;
p = pre;
}
return root.next;
}
}
三、146. LRU 缓存
题目链接:https://leetcode.cn/problems/lru-cache/description/
思路:非常经典的题目,最近最少使用,我们需要构建一个双向链表和哈希表,其中双向链表应该有虚拟的头结点和尾结点,方便进行添加删除操作,其他的是常规操作。
class LRUCache {
int capacity;
Map<Integer, Node> map;
DoubleList list;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
list = new DoubleList();
}
public int get(int key) {
if(!map.containsKey(key)) return -1;
Node temp = map.get(key);
makeRecently(temp);
return temp.value;
}
public void put(int key, int value) {
if(map.containsKey(key)) {
Node temp = map.get(key);
temp.value = value;
makeRecently(temp);
return;
}
if(list.size == capacity) {
Node temp = list.deleteFirst();
map.remove(temp.key);
}
Node temp = new Node(key, value);
list.add(temp);
map.put(key, temp);
}
void makeRecently(Node temp) {
list.delete(temp);
list.add(temp);
}
}
class DoubleList {
int size = 0;
Node start, end;
DoubleList() {
start = new Node();
end = new Node();
start.right = end;
end.left = start;
}
void delete(Node temp) {
temp.left.right = temp.right;
temp.right.left = temp.left;
temp.left = null;
temp.right = null;
size--;
}
Node deleteFirst() {
if(start.right == end) return null;
Node temp = start.right;
delete(temp);
return temp;
}
void add(Node temp) {
end.left.right = temp;
temp.left = end.left;
temp.right = end;
end.left = temp;
size++;
}
}
class Node{
int key, value;
Node left, right;
Node(){}
Node(int k, int v) {
key = k;
value = v;
}
}
四、215. 数组中的第K个最大元素
题目链接:https://leetcode.cn/problems/kth-largest-element-in-an-array/description/
思路:使用快速排序超时,又要求时间复杂度为O(N),使用桶排序最合数不过了。
桶排序:即把所有的数作为索引,放到一个新数组里去,即放到桶里,出现多次即累加,然后从后往前遍历减去次数,即可得到第K个最大的元素。
class Solution {
public int findKthLargest(int[] nums, int k) {
int[] count = new int[20001];
for(int i : nums) {
count[i + 10000]++;
}
for(int i = 20000; i > 0; i--) {
k = k - count[i];
if(k <= 0) return i - 10000;
}
return 0;
}
}
快排:
class Solution {
public int findKthLargest(int[] nums, int k) {
quickSort(nums, 0, nums.length-1);
return nums[nums.length - k];
}
void quickSort(int[] nums, int left, int right) {
if(left >= right) return;
int base = nums[left];
int i = left, j = right;
while(i < j) {
while(nums[j] >= base && i < j) j--;
while(nums[i] <= base && i < j) i++;
swap(nums, i, j);
}
swap(nums, left, j);
quickSort(nums, left, j-1);
quickSort(nums, j+1, right);
}
void swap(int[] nums, int x, int y) {
int t = nums[x];
nums[x] = nums[y];
nums[y] = t;
}
}
五、25. K 个一组翻转链表
题目链接:https://leetcode.cn/problems/reverse-nodes-in-k-group/description/
思路:
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 reverseKGroup(ListNode head, int k) {
ListNode root = new ListNode(-1, head);
ListNode slow = root, fast =head;
int i = 0;
while(fast != null) {
i++;
fast = fast.next;
if(i % k == 0) {
slow = reverse(slow, fast);
}
}
return root.next;
}
ListNode reverse(ListNode a, ListNode b) {
ListNode r = a, p1 = a.next, p2 = p1;
r.next = null;
while(p1 != b) {
ListNode pre = p1.next;
p1.next = r.next;
r.next = p1;
p1 = pre;
}
p2.next = b;
return p2;
}
}