Leetcode 相关知识点 day5

Leetcode 相关知识点 day5

#####用于作者每日有需所作笔记

1.岛屿问题

**二叉树DFS 的基本结构**
void traverse(TreeNode root) {
    // 判断 base case
    if (root == null) {
        return;
    }
    // 访问两个相邻结点:左子结点、右子结点
    traverse(root.left);
    traverse(root.right);
}



**表格DFS 的基本结构**
void dfs(int[][] grid, int r, int c) {
    // 判断 base case
    // 如果坐标 (r, c) 超出了网格范围,直接返回
    if (!inArea(grid, r, c)) {
        return;
    }
    // 访问上、下、左、右四个相邻结点
    dfs(grid, r - 1, c);
    dfs(grid, r + 1, c);
    dfs(grid, r, c - 1);
    dfs(grid, r, c + 1);
}

// 判断坐标 (r, c) 是否在网格中
boolean inArea(int[][] grid, int r, int c) {
    return 0 <= r && r < grid.length 
        	&& 0 <= c && c < grid[0].length;
}

网格结构的 DFS 与二叉树的 DFS 最大的不同之处在于:
遍历中可能遇到遍历过的结点。这是因为,网格结构本质上是一个「图」,
我们可以把每个格子看成图中的结点,每个结点有向上下左右的四条边。
在图中遍历时,自然可能遇到重复遍历结点。



***我们在框架代码中加入避免重复遍历的语句:***
void dfs(int[][] grid, int r, int c) {
    // 判断 base case
    if (!inArea(grid, r, c)) {
        return;
    }
    // 如果这个格子不是岛屿,直接返回
    if (grid[r][c] != 1) {
        return;
    }
    grid[r][c] = 2; // 将格子标记为「已遍历过」
    
    // 访问上、下、左、右四个相邻结点
    dfs(grid, r - 1, c);
    dfs(grid, r + 1, c);
    dfs(grid, r, c - 1);
    dfs(grid, r, c + 1);
}

// 判断坐标 (r, c) 是否在网格中
boolean inArea(int[][] grid, int r, int c) {
    return 0 <= r && r < grid.length 
        	&& 0 <= c && c < grid[0].length;
}


2.二维数组根据第一列排序

Arrays.sort(prerequisites,new Comparator<int[]>() {
	public int compare(int[] o1, int[] o2) {
	     return o1[0]-o2[0];
	}
});



如果第一列相同,就根据第二列排序
Arrays.sort(ts_id,new Comparator<int[]>() {
    @Override
    public int compare(int[] o1, int[] o2) {
        if (o1[0] == o2[0]) {
	    return o1[1] - o2[1];
	}		
	return o1[0]-o2[0];
    }
});

3.常用小技巧总结

*****************************************************

利用按位异或的性质,可以得到 
mid 是偶数时,mid + 1 = mid ⊕ 1
mid 是奇数时,mid − 1 = mid ⊕ 1

*****************************************************

三指针求和时,往往对于有序数组,只需遍历第一个指针,第二第三指针同时从首尾同步进行。
当总值较大不满足时,左移第三个指针,在决定是否右移第二个指针。

*****************************************************

往往无序的数组,进行子数组操作时,不能使用滑动窗口。
滑动窗口多用于操作有序或有规律的数组。
无序的数组常用动态规划和双指针算法。

*****************************************************

自然二进制码 ^ 自然二进制码右移一位,即G = B ^ (B >> 1)

*****************************************************

当给定链表需要从中间截断时,即归并排序。需注意寻找中间节点时易造成栈溢出。
ListNode slow = head;
ListNode fast = head.next;    //若改成fast = head; ---> 栈溢出
while(fast != null && fast.next != null){
    slow = slow.next;
    fast = fast.next.next;
}

*****************************************************

前缀树的初始化
class Trie {
    private Trie[] children;
    private boolean isEnd;

    public Trie() {
        children = new Trie[26];
        isEnd = false;
    }
    
    public void insert(String word) {
        Trie node = this;
        ......
    }
    
*****************************************************

**完全二叉树**:
将完全二叉树按序放入数组中,若数组长度为heasize,
最后一个节点的位置为heapsize-1,该节点的父节点的位置为heapsize-1-1/2//left和right表示当前父节点i的两个左右子节点。
int left = i * 2 + 1, right = i * 2 + 2, largest = i;
        
*****************************************************

统计1到n每个数的二进制含1个数。
用动态规划求,传递函数为:
dp[i] = dp[i/2];    若i为偶数;
dp[i] = dp[i-1]+1;  若i为奇数;

*****************************************************

求路径和往往用前缀和结合Map实现低时间复杂度。
值得注意的是:递归时需要状态还原。

*****************************************************

寻找数组中未出现的数字,将数组中的数字当做索引,进行操作。
后续遍历每个位置,不达要求的即数组中没出现过得数字。

*****************************************************

一次遍历,双指针同时左右两边向中间移动。
for(int i = 0; i < nums.length; i++){
	left = i;
	right = nums.length-i-1;
}


*****************************************************

4.水容量问题

水容量:容量大小取决于短板高度。 双指针从左右两段开始往内缩进,每次让短板缩进。如下图:

请添加图片描述

5.排序复杂度

划分

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值