本博客仅做学习笔记,如有侵权,联系后即刻更改
科普:
参考文章
参考文章
时间复杂度
时间复杂度考虑最坏时间复杂度
空间复杂度
在衡量代码的空间复杂度的时候,只关心运行过程中临时占用的内存空间
for的增强型循环
- 增强for循环遍历数组时使用的普通for循环,而遍历集合时使用的Iterator迭代器
- 在使用增强型for循环不支持遍历时删除元素
- 使用增强型for循环时,对遍历的集合需要做null判断,不然可能引发空指针异常。
快慢指针
- 使用速度不同的指针(可用在链表、数组、序列等上面),来解决一些问题
- 快指针 fast 指向当前要和 val 对比的元素,慢指针 slow 指向将被赋值的位置
滑动窗口
- 一般就用在数组或者字符串上
- 滑动:窗口可以按照一定的方向移动。
- 窗口:窗口大小可以固定,也可以不固定,此时可以向外或者向内,扩容或者缩小窗口直至满足条件
模拟题
- 模拟题本身不涉及算法,就是单纯根据题目所描述的模拟整个过程从而得到最后的结果
移除元素
- 是快慢指针的经典题目
暴力双层循环
class Solution {
public int removeElement(int[] nums, int val) {
int num = nums.length;
for(int i=0; i<num; i++){
if(nums[i] == val){
for(int j=i; j<num-1; j++){
nums[j] = nums[j+1];
}
num--;
i --;
}
}
return num;
}
}
快慢指针
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
int fast = 0;
for(; fast<nums.length; fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
}
题目解析
这是一道模拟题,难度中等,面试出现频率极高时空复杂度分析
矩阵大小为 n²,需要全部遍历且填充,所以时间复杂度为 O(n²)
此外额外维护了一个大小为 n² 的结果矩阵,所以空间复杂度为 O(n²)
class Solution {
public int[][] generateMatrix(int n) {
int w[][]= new int [n][n];
int s=0,x=n-1,z=0,r=n-1;
int sum=1,i;
while(sum <= n*n){
for(i=z; i<=r; i++)
w[s][i] = sum++;
s++;
for(i=s; i<=x; i++)
w[i][r] = sum++;
r--;
for(i=r; i>=z; i--)
w[x][i] = sum++;
x--;
for(i=x; i>=s; i--)
w[i][z] = sum++;
z++;
}
return w;
}
}
滑动窗口
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int right=0, left=0, sum=0, num=Integer.MAX_VALUE;
for(; right<nums.length;){
sum += nums[right++];
while(sum >= target){
num = Math.min(num, right-left);
sum -= nums[left++];
}
}
return num == Integer.MAX_VALUE ? 0 : num;
}
}
双指针法来解决,left 指向下标 0,right 指向下标 n - 1
class Solution {
public int[] sortedSquares(int[] nums) {
int right = nums.length-1, left = 0;
int array[] = new int [nums.length];
int pos = nums.length-1;
while(left <= right){
nums[left] = Math.abs(nums[left]);
nums[right] = Math.abs(nums[right]);
if(nums[left] > nums[right])
array[pos--] = (int)Math.pow(nums[left++], 2);
else {
array[pos--] = (int)Math.pow(nums[right--], 2);
}
}
return array;
}
}
单链表
链表中的每个节点只包含一个指针域
双向链表
相比起单链表来说
- 多了一个前驱指针 prev,指向前驱节点
头指针
链表的必备元素且无论链表是否为空,不能为空
后继指针
下个节点地址的指针
快慢指针
/**
* 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 removeNthFromEnd(ListNode head, int n) {
ListNode a = head;
ListNode b = head;
for(int i =0; i<n; i++){
a = a.next;
}
// 删除头节点
if(a == null) return head.next;
while(a.next != null){
a = a.next;
b = b.next;
}
b.next = b.next.next;
return head;
}
}
/**
* 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 swapPairs(ListNode head) {
ListNode fakeNode = new ListNode(0);
fakeNode.next = head;
ListNode pre = fakeNode;
while(pre.next != null && pre.next.next != null){
// 存储相邻两节点的后继节点
ListNode temp = head.next.next;
pre.next = head.next;
head.next.next = head;
head.next = temp;
pre = head;
head = head.next;
}
return fakeNode.next;
}
}
每次循环K个节点,翻转后链接回去
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode hair = new ListNode(0);
hair.next = head;
ListNode pre = hair;
while (head != null) {
ListNode tail = pre;
// 查看剩余部分长度是否大于等于 k
for (int i = 0; i < k; ++i) {
tail = tail.next;
if (tail == null) {
return hair.next;
}
}
ListNode nex = tail.next;
ListNode[] reverse = myReverse(head, tail);
head = reverse[0];
tail = reverse[1];
// 把子链表重新接回原链表
pre.next = head;
tail.next = nex;
pre = tail;
head = tail.next;
}
return hair.next;
}
public ListNode[] myReverse(ListNode head, ListNode tail) {
ListNode prev = tail.next;
ListNode p = head;
while (prev != tail) {
ListNode nex = p.next;
p.next = prev;
prev = p;
p = nex;
}
return new ListNode[]{tail, head};
}
}
快慢指针,如果快指针反过来追上了慢指针,则存在环
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode s = head, f = head;
while(f != null && f.next != null){
s = s.next;
f = f.next.next;
if(s == f) return true;
}
return false;
}
}
public class Solution {
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 flag = head;
while(flag != slow){
flag = flag.next;
slow = slow.next;
}
return flag;
}
}
return null;
}
}
小小励志
有些事你现在不做,一辈子都不会做了。
如果你想做一件事,全世界都会为你让路。
《搭车去柏林》