算法篇
前言
本次算法入门训练主要训练以下三个内容:
- 以特殊数据结构为载体的算法结构,比如:数组、链表、栈、二叉树等
- 以考察常见算法思想基础的算法题,比如:动态规划、贪心、回溯等
- 基于某种场景包装下的1和2
提示:以下是本篇文章正文内容
内容
第一题:替换空格
解题思路:字符串操作问题,虽然是替换问题但是最后的整体字符串会变长必然会有字符移动问题,移动一定是向后移现在无非是移动多少的问题。那么定义新老索引,给自指向新老空间的结尾,如果是空格,就连续放入“%20”,其他平移即可。
OJ链接:第一题
public class Solution {
public String replaceSpace(StringBuffer str) {
//1.首先确认当前字符串中有多少空格
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == ' ') {
count++;
}
}
//2.对源字符串进行扩充,每有一个空格字符,字符串就增加两个长度
int new_strLength = str.length() + count * 2;
//3.然后确定新字符串的尾索引和旧字符串的尾索引,依次进行替换即可
int old_end = str.length() - 1;
int new_end = new_strLength - 1;
str.setLength(new_strLength);
while(old_end >= 0 && new_end >= 0){
if(str.charAt(old_end) == ' '){
str.setCharAt(new_end--,'0');
str.setCharAt(new_end--,'2');
str.setCharAt(new_end--,'%');
old_end--;
}else{
str.setCharAt(new_end,str.charAt(old_end));
old_end--;
new_end--;
}
}
return str.toString();
}
}
第二题:从尾到头打印链表
解题思路:这道题整体解决思路很多,可以使用stack,可以递归,也可以将数据保存数组,逆序数组,我们就用递归写
OJ链接:第二题
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
public class Solution {
public void printListFromTailToHeadHelper(ArrayList<Integer> list,ListNode listNode){
if(listNode == null){
return;
}
printListFromTailToHeadHelper(list,listNode.next);
list.add(listNode.val);
}
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
//递归 先把当前节点后面的节点输出,才能输出当前节点,范围逐渐缩小,也就是一个递归。
//还可以用栈,数组逆转的方法。
ArrayList<Integer> list = new ArrayList<>();
if(listNode == null){
return list;
}
printListFromTailToHeadHelper(list, listNode);
return list;
}
}
第三题:重建二叉树
解题思路:了解二叉树前序中序后序遍历的特性,前序遍历按根左子树右子树遍历那么第一个节点肯定是根节点,中序遍历是左根右,通过前序确定的根在到中序中确定其左右子树其它进行递归即可。
OJ链接:第三题
import java.util.*;
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTreeHelper(ArrayList<Integer> pre, int pre_start,
int pre_end, ArrayList<Integer>vin, int vin_start, int vin_end) {
if (pre_start > pre_end || vin_start > vin_end) {
return null;
}
//前序序列的第一个元素就是根节点
TreeNode root = new TreeNode(pre.get(pre_start));
//根据中序序列,确定根节点的左子树和右子树
for (int i = vin_start; i <= vin_end; i++) {
//找到了,确定左子树有多少节点,右子树有多少节点
//中序序列的结构为 [vin_start,i - 1] i [i+1,vin_end]
//前序序列需要向后数,根据中序序列当中根节点左边节点的个数-1,来确定左子树的节点
if (vin.get(i) == pre.get(pre_start)) {
root.left = reConstructBinaryTreeHelper(pre, pre_start+1,
pre_start + i - vin_start, vin, vin_start, i - 1);
root.right = reConstructBinaryTreeHelper(pre, pre_start + i - vin_start + 1,
pre_end, vin, i + 1, vin_end);
break;
}
}
return root;
}
public TreeNode reConstructBinaryTree(ArrayList<Integer> pre,
ArrayList<Integer> vin) {
if(pre.size() == 0 || vin.size() == 0){
return null;
}
//递归构建
return reConstructBinaryTreeHelper(pre, 0, pre.size() - 1, vin, 0,
vin.size() - 1);
}
}
第四题:斐波那契数列
解题思路:这题可以很经典的引入动规,也可以用递归做但是一但n的数值过大递归的效率就很慢了,也可以优化一下动规用迭代做。
OJ链接:第四题
public class Solution {
public int Fibonacci(int n) {
//迭代
if(n == 0){
return n;
}
if(n <= 2){
return 1;
}
int frist = 1;
int second = 1;
int third = 0;
while(n > 2){
third = frist + second;
frist = second;
second = third;
n--;
}
return third;
}
}
总结
以上就是今天训练的内容,今天尝试了几种数据结构,感觉还不错,需要几种数据结构的专题训练。