刷题笔记2
深度优先搜索的汇总:
首先准备一个TreeNode类:
class TreeNode{
datatype data;
TreeNode left;
TreeNode right;
public TreeNode(datatype data,TreeNode left,TreeNode right){
this.data = data;
this.left = left;
this.right = right;
}
}
(1). 递归法
解二叉树的中序遍历
class Solution{
//主程序方法
public List<Integer> inorderTraversal(TreeNode root){
List<Integer> list = new LinkedList<>();
RecursionTraversal(root,list);
return list;
}
//递归方法
public void RecursionTraversal(TreeNode root,List<Integer> list){
if(root==null){
return;
}
RecursionTraversal(root.left,list);
list.add(root.data);
RecursionTraversal(root.right,list);
}
}
由于是中序遍历
,所以应先查找二叉树左半部分的结点,接着查找根结点,最后查找右边的结点。
算法优化:
1.优化了判断条件:
在递归方法中添加了判断当前结点是否为空的条件后,无需在递归处添加if条件限制(例如
if(root.left!=null){...}
)在进入递归后的if处可以被检测是否存在子节点。
2.减少了在主程序方法中的为空判断条件:
应优先创建list集合,最后如果为空则返回一个空集合,而不是返回一个NULL。否则当二叉树为
[]
时,会输出一个null而不是[]
。
总结:
递归法相比循环法仍然可以实现回溯思想
,否则当遍历指针指向左右结点时则无法回到父节点,且代码较为精炼。
(2).循环法
解二叉树的中序遍历
class Solution{
public List<Integer> inorderTraversal(TreeNode root){
List<Integer> list = new LinkedList <>();
TreeNode curr = root;
if (root == null){
return list;
}
Stack<TreeNode> stack = new Stack <>();
while(!stack.isEmpty() || curr!=null){
while(curr!=null){
//System.out.println(curr.data);
stack.push(curr);
curr = curr.left;
}
TreeNode currRoot = stack.pop();
//System.out.println(currRoot.data);
list.add(currRoot.data);
curr = currRoot.right;
}
return list;
}
}
循环法要实现回溯算法应该使用额外的空间(此题中的栈
数据结构),使用栈将父节点的内存地址储存起来,便于访问其根结点右边的结点。
(3).二叉搜索树的范围和
LeetCode938:二叉搜索树的范围和
* 给定二叉搜索树的根结点root,返回值位于范围[low,high]之间所有结点的值的和。
*
* EXP:
* Input:root = [18,9,27,6,15,24,30,3,null,12,null,21],
low = 18,high = 24。
* Output:32
class Solution{
public int rangeSumBST(TreeNode root,int low,int high){
int sum = 0;
if (root == null){
return sum;
}
if (root.val>=low&&root.val<=high){
sum += root.val;
sum+=rangeSumBST(root.left,low,high);
sum+=rangeSumBST(root.right,low,high);
}
else if (root.val < low && root.right!=null){
sum = rangeSumBST(root.right,low,high);
}
else if (root.val > high && root.left!=null){
sum = rangeSumBST(root.left,low,high);
}
return sum;
}
}
(4).岛屿数量
LeetCode200:岛屿数量
* 给你一个由"1"(陆地)和"0"(水)组成的二维网格,请计算网络中的岛屿个数。
*
* 岛屿始终被水包围,并且每座岛只能由水平方向和竖直方向上相邻的陆地连接而成。
*
* 假设网格的四条边均被水包围。
案例:
{{'1','1','0','0','0'},
{'1','1','0','0','0'},
{'0','0','1','0','0'},
{'0','0','0','1','1'}};
class Solution{
//主程序函数
public int numIslands(char[][] grid){
int count = 0;
if (grid == null||grid.length==0){
return 0;
}
int width = grid.length;
int length = grid[0].length;
for (int i = 0;i < width;i++){
for (int j = 0;j < length;j++){
if (grid[i][j] == '1'){
count++;
dfs(grid,i,j);
}
}
}
return count;
}
//递归函数
private static void dfs(char[][] grid,int i,int j){
int width = grid.length;
int length = grid[0].length;
if (i < 0||i >= width||j < 0||j >= length||grid[i][j]=='0'){
return;
}
grid[i][j] = '0';
dfs(grid,i,j+1);
dfs(grid,i+1,j);
dfs(grid,i-1,j);
dfs(grid,i,j-1);
}
}
该题可使用多种方法进行求解:
dfs基本思路:使用单指针遍历二维数组中的每一个数,每遍历一个数,判断该位置是否为陆地:
如果该地是陆地,则将其本身位置,以及其四面八方都变为水域,这部分即为一片岛屿。
如果这部分本身是海域,则继续遍历即可。