努力经营当下,直至未来明朗!
普通小孩也要热爱生活!
1. 字符串替换空格
替换空格
1)替换:修改的是原字符串
2)将空格替换为%20,也就是一个字符位置变长为三个字符位置(一个空格增两个字符);字符串长度变长,也就是原来的字符串要向后移动
3)计算新的字符串长度:原字符串长度+2*空格数
4)从后往前遍历!
5)保证下标的合法性
6)可变长字符串,重新设置一下字符串长度
代码:
public class Solution {
public String replaceSpace(StringBuffer str) {
// 计算空格个数(为了计算新字符串的长度)
int space = 0;
for(int i=0; i<str.length(); i++) {
if(str.charAt(i) == ' ') {
space++;
}
}
// 计算字符串长度以及最末指针
int new_length = str.length() + 2*space;
int old_index = str.length()-1;
int new_index = new_length - 1;
// 设定新的字符串长度
str.setLength(new_length);
// 进行循环替换(合法性判断)
while(new_index>=0 && old_index>=0) {
if(str.charAt(old_index) == ' ') {
// new_index:先用后减
str.setCharAt(new_index--,'0');
str.setCharAt(new_index--,'2');
str.setCharAt(new_index--,'%');
old_index--;
} else {
// 直接进行赋值替换就行
str.setCharAt(new_index,str.charAt(old_index));
new_index--;
old_index--;
}
}
return str.toString();
}
}
2. 链表相关:从尾到头打印链表
从尾到头打印链表
1)思路:
①逆序 -> 定义栈结构;
②遍历后保存在数组中;
③递归(重点!)
2)代码:
① 栈结构:
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
// 用来保存出栈的元素
ArrayList<Integer> list = new ArrayList<>();
// 首先进行判空操作
if(listNode == null) {
return list;
}
// 不空的情况下:进行入栈操作
Stack<Integer> stack = new Stack<>();
while(listNode != null) {
stack.push(listNode.val);
listNode = listNode.next;
}
// 然后出栈存入list中
while(!stack.empty()) {
list.add(stack.pop());
}
return list;
}
}
② 递归——如果要将前面的元素加入到新链表中,就要先完成之后元素加入链表。
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
public class Solution {
// 重写方法
private static void printListFromTailToHead(ArrayList<Integer> list,ListNode listNode) {
if(listNode == null) {
return;
}
printListFromTailToHead(list,listNode.next);
list.add(listNode.val);
}
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<>();
printListFromTailToHead(list,listNode);
return list;
}
}
3. 重建二叉树
重建二叉树
1)二叉树:前中后序遍历(针对根结点)
2)方法:从前序遍历中找到根结点(首元素),然后拿着该根结点去中序遍历中找,然后就可以将中序遍历划分为左右子树,然后每棵子树又可以根据自己的根结点再划分为左右子树;而中序遍历的根结点左边有几个元素就代表前序遍历往后数几个元素都是左子树的元素,再之后的元素就是右子树元素。也就是:递归!
3)思路:针对前序和中序遍历划分根结点以及左右子树
4)一定要注意条件判断!!
代码:
import java.util.*;
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
// 这里使用的是: 闭区间!
private static TreeNode reConstructBinaryTree(int[] pre,int pre_start,int pre_end,int[] vin,int vin_start,int vin_end) {
// 判断条件:注意这个条件一定要存在!!否则编译失败!
if(pre_start>pre_end || vin_start>vin_end) {
return null;
}
// 根结点:前序遍历的第一个元素就是
TreeNode root = new TreeNode(pre[pre_start]);
// 然后再中序遍历中找到根结点位置
// 注意开始遍历的位置!
for(int i=vin_start; i<=vin_end; i++) {
if(root.val == vin[i]) {
// 找到了根结点,然后开始构建左右子树
// 一定要注意参数!!
// 左子树
root.left = reConstructBinaryTree(pre,pre_start+1,pre_start+1+i-vin_start-1,vin,vin_start,i-1);
// 右子树
root.right = reConstructBinaryTree(pre,pre_start+1+i-vin_start,pre_end,vin,i+1,vin_end);
break;
}
}
return root;
}
public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
// 首先进行判断
if(pre==null || vin==null || pre.length!=vin.length) {
return null;
}
// 其实关键就是:找到根结点以及左右子树
return reConstructBinaryTree(pre,0,pre.length-1,vin,0,vin.length-1);
}
}
4. fib数列[动态规划]
菲波那切数列
1)fib:0 1 1 … 后面的项就是前两项之和
2)思路:① 迭代; ② 递归(递归+剪枝!)
3)代码:
① 迭代:3)循环(注意循环条件)以及third的初始值
public class Solution {
public int Fibonacci(int n) {
if(0 == n) {
return n;
}
int first = 1;
int second = 1;
int third = 1; // 定义1是方便不判断first、second就直接输出
while(n > 2) {
third = first + second;
first = second;
second = third;
n--; // 一定要注意循环条件的改变!
}
return third;
}
}
② 递归:递归(重复计算+调用函数成本,会使效率变低!一般不推荐使用)
public class Solution {
public int Fibonacci(int n) {
if(0 == n) {
return 0;
}
if(n <= 2) {
return 1;
}
return Fibonacci(n-1) + Fibonacci(n-2);
}
}
③ 如果要使用递归的话,就进行剪枝操作(递归+剪枝)
剪枝:其实就是需要借助Map进行存储,每次需要fib的时候就查看在map中是否存在,存在就直接使用,不存在就计算后存入map。
import java.util.*;
public class Solution {
// 递归+剪枝(Map)
// 注意:是Map = HashMap
private Map<Integer,Integer> map = new HashMap<>();
public int Fibonacci(int n) {
if(n==0 || n==1) {
return n;
}
if(n == 2) {
return 1;
}
// 进行递归+剪枝
int ppre = 0; // n-2
if(map.get(n-2) == null) {
// 说明该值在map中不存在
// 计算并加入
ppre = Fibonacci(n-2);
map.put(n-2,ppre);
} else {
// 此时说明找到
ppre = map.get(n-2);
}
int pre = 0; // n-1
if(map.get(n-1) == null) {
// 说明该值在map中不存在
// 计算并加入
pre = Fibonacci(n-1);
map.put(n-1,pre);
} else {
// 此时说明找到
pre = map.get(n-1);
}
return ppre + pre;
}
}