leetcode 题解 刷题笔记 清晰明了 面试突击

这篇博客详细介绍了如何解决《剑指 Offer》中的多个算法问题,包括数组、链表、二叉树等数据结构的操作。涉及的问题有:寻找数组中重复的数字、二维数组查找、替换空格、从尾到头打印链表、重建二叉树、序列化二叉树、用两个栈实现队列、斐波那契数列、青蛙跳台阶问题、旋转数组的最小数字、矩阵中的路径、机器人的运动范围、剪绳子问题、二进制中1的个数、数值的整数次方、打印从1到最大的n位数、删除链表节点、表示数值的字符串、调整数组顺序使奇数位于偶数前面、链表中倒数第k个节点、反转链表、合并两个排序的链表等。博客内容涵盖数据结构、算法和递归等多种编程技巧。
摘要由CSDN通过智能技术生成

剑指 Offer 03. 数组中重复的数字

关键词:Set重复
问题:从一维数组中找出一个重复数
解决方法:
使用Set存储,add方法,当集合已有元素时返回false,表明重复了。

剑指 Offer 04. 二维数组中的查找

关键词:数组递增
问题:从左上角向右向下递增的二维数组,查找某个值。
解决方法:
从右上角开始

  • 当前值等于目标,返回true
  • 当前值大于目标,向左移动一列
  • 当前值小于目标,向下移动一行

剑指 Offer 05. 替换空格

关键词:StringBuffer
问题:将字符串s中的空格替换为某个串
解决方法:
使用StringBuffer sb = new StringBuffer();
char[] arr = s.toCharArray();
sb.append(arr[i]);
当arr[i]为空格时,sb.append(“xx串”);

剑指 Offer 06. 从尾到头打印链表

关键词:链表倒序
问题:给你链表头部,从尾到头打印链表
解决方法:

  1. 正序遍历链表,用栈保存。栈弹出的顺序即为答案。
  2. 使用递归方法,在递过去的时候不管,归回来时,将链表节点的值加入list中,即为答案。

关键api:
new Arraylist<>();
new LinkedList<>();

剑指 Offer 07. 重建二叉树

关键词:重建二叉树前序遍历中序遍历
问题:给你二叉树的不含空节点的前序遍历和中序遍历结果,让你重建出二叉树
解决方法:
递归函数

TreeNode dfs(int left, int right) {
   
	preorder_index++;
	//map 是 inorder[i] -> i
	Integer pos = map.get(preorder[preorder_index]);
	if(pos!=null){
   
		TreeNode res = new TreeNode(preorder[preorder_index]);
		res.left = dfs(left, pos-1);
		res.right = dfs(pos+1, right);
		return res;
	}
	return null;
}

剑指 Offer 37. 序列化二叉树

关键词:前序遍历重建二叉树
问题:实现二叉树的序列化和反序列化算法
解决方法:
序列化:含空节点的前序遍历
反序列化:按前序遍历的样子建树

public String serialize(TreeNode root) {
   
	StringBuilder builder = new StringBuilder();
	serialize0(root, builder);
	builder.deleteCharAt(builder.length()-1);
	return builder.toString();
} 
private void serialize0(TreeNode root, StringBuilder builder) {
   
	if(!root)
		builder.append("null,");
	builder.append(root.val).append(",");
	serialize0(root.left);
	serialize0(root.right);
}
	
public TreeNode deserialize(String encode) {
   
	String[] strs = encode.split(",");
	return deserialize0(Arrays.asList(strs));
}
private TreeNode deserialize0(List<String> list){
   
	if(list.get(0).equals("null")) {
   
		list.remove(0);
		return null;
	}
	TreeNode root = new TreeNode(list.get(0));
	root.left = deserialize0(list);
	root.right = deserialize0(list);
}

剑指 Offer 09. 用两个栈实现队列

关键词:两个栈
问题:用两个栈实现队列的offer和poll方法
解决方法:
使用两个栈offerStack、pollStack
offer方法将元素push进offerStack
poll方法

  • 若pollStack为空,将offerStack栈混洗到pollStack
  • 若pollStack不为空,直接pop。

关键api:
Deque stack = new LinkedList<>();

剑指 Offer 10- I. 斐波那契数列

关键词:斐波那契数列
问题:求斐波那契数列的第n项,答案需取模1000000007。
解决方法:
用迭代求。

int a = 0, b = 1, c = 0, t = 1000000007;
for(int i = 3;i<=n;i++){
   
	c = (a + b)%t;
	a = b;
	b = c;
}

剑指 Offer 10- II. 青蛙跳台阶问题

关键词:斐波那契数列
问题:青蛙一次可跳1或2级台阶,求跳到n级台阶有多少种跳法。
解决方法:递推式和斐波那契数列的一样,只是起始值是1、1。仿照斐波那契数列的解法即可。

剑指 Offer 11. 旋转数组的最小数字

关键词:旋转数组二分查找变形
问题:对存在重复值的升序数组旋转一次,求数组的最小值。旋转指将数组开始的元素搬到末尾,例如[1,2,3,4,5] -> [3,4,5,1,2]。
解决方法:

  1. 线性遍历数组
  • 当arr[i]>arr[i+1]时,arr[i+1]为最小值
  • 未出现arr[i]>arr[i+1]的情况,arr[0]为最小值
    此方法时间效率为O(n)
  1. 二分查找O(log n)
public int binarySearchMinValue(int[] arr) {
   
	int left = 0, right = arr.length-1;
	while(left<=right){
   
		int mid = left + (right - left)/2;
		if(arr[mid]==arr[right])
			right--;
		else if(arr[mid]>arr[right])
			left = mid + 1;
		else 
			right = mid;
	}
	return left<arr.length?arr[left]:-1;
}

剑指 Offer 12. 矩阵中的路径

关键词:深度优先搜索矩阵搜索
问题:在二维字符数组中查找是否存在相邻的格子像线一般连接成单词word。
解决方法:
深度优先搜索

private char[] word;
private char[][] arr;
boolean dfs(int i, int j, int k) {
   
	if(i<0||i>=arr.length||j<0||j>=arr[0].length || arr[i][j]!=word[k])
		return false;	
	if(k==word.length-1)
		return true;			
	arr[i][j] = '\0';
	boolean res = dfs(i+1,j,k+1) || dfs(i-1,j,k) || dfs(i,j+1,k) || dfs(i,j-1,k);
	arr[i][j] = word[k];
	return res;
}

剑指 Offer 13. 机器人的运动范围

关键词:广度优先搜索
问题:从mxn矩阵的0x0位置能到达的最多格子数。横坐标x、纵坐标y,应该满足某个条件。
解决方法:
广度优先搜索

class MyClass {
   
	int x;
	int y;
	public MyClass(int a, int b){
   
		x = a;
		y = b;
	}
}
public int bfs(int m, int n) {
   
	int count = 0;
	int[][] offset = new int[][]{
   {
   
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值