《剑指offer》读书笔记

本文深入探讨了面试准备策略,包括电话、视频和现场面试的技巧,强调了沟通能力和技术功底的重要性。提供了丰富的算法题解,涵盖数组、链表、二叉树等数据结构,以及动态规划、贪心算法等技术要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一章

电话面试要尽可能形象化的语言把细节说清楚
千万不要不懂装懂,这是面试大忌,大胆多提问 直到弄清楚面试官意图
视频面试:良好的代码命名和缩进对齐习惯,能够进行单元测试,测试在前开发在后
碰到有问题了,就设置断电,单步追踪,查看内存,分析调用栈
现场面试:准备好向面试官提问的 问题

面试分为 行为面试 技术面试和应聘者提问
行为面试:自我介绍,项目经验。用star模型描述自己经历的项目
Situation Task Action Result
不要用负责这么重的字眼
做软件开发的,可以写基于什么工具在哪个平台下应用了什么样的技术
你在项目中碰到的最大的问题是什么,从项目中你学到了什么,与其他团队成员有什么冲突。

突出自己完成的工作和取得的成绩

了解 属于上过课看过书 没有关系的公司就不要加了解了
熟悉 通过查阅相关文档可以独立解决大部分问题
精通 得心应手 ,别人请教我们能够解决

为什么跳槽 工作了一段时间 没有了激情,找一份更有挑战的工作。

技术面试:
一般五个方面,扎实的基础知识,能写高质量的代码,分析问题的思路清晰,优化时间效率和空间效率。
遇到复杂的问题,应聘者可以通过画图,举具体例子分析 和 分解复杂问题等方法先厘清思路然后动手编程。不断优化时间效率和空间效率,力求找到最优的解法。

什么是扎实的基本功: 编程语言 ,数据结构和算法
数据结构:链表,树,栈,队列和哈希表
链表和二叉树问的最多
链表的插入和删除节点了如指掌,对二叉树的各种遍历方法循环和递归方法烂熟于胸。
重点掌握二分查找,归并排序和快速查找
要求高一点就是动态规划和贪心算法

高质量的代码
边界条件,比如把字符串变成数字里面,字符串中有非数字字符和正负号,考虑最大的正整数和负整数以及溢出。

面试的时候要有鲁棒型,怎么做呢,动手之前想好测试用例。
清晰的思路:举几个简单的具体例子让自己理解问题
用图形表示抽象的数据结构,很多基于递归的思路,包括分治法和动态规划,把复杂的问题分解成一个多个问题。
总结:画图能使抽象问题形象化,举例使抽象问题具体化,分解使复杂问题简单化。

除了展示自己技术功底还有自己的软实力,沟通能力和学习能力
知识迁移的能力
面试前做足功课,到网上搜集一些相关的信息,对公司成立时间,主要业务,职位要求了然于胸

第二章

数组可以说是最简单的一种数据结构,它占据连续的内存并按照顺序存储数据。可以在O(1)时间读写任何元素,时间效率很高。也可以变成哈希表,形成“键值-值”配对
为了解决数组空间效率不高的问题,设计了动态数组,就像C++ STL中的vector

数组中重复的数字

方法一:
直接两重循环,用==找到相同 的数
方法二:
建立哈希表,判断这个数字是不是有过了。时间复杂度时O(n),空间复杂度O(n)

function duplicate(numbers, duplication)
{
    if(numbers.length ==1) return false;
    if(numbers == null) return false;
    let hash = Array(numbers.length);
    for (let i = 0; i< numbers.length; i++){
        if(hash[numbers[i]]){
            duplicationp[0] = numbers[i];
            return true;
        }else{
            hash[numbers[i]] = numbers[i];
        }
    }
    return false;
}

方法
方法三:
先排序,排序一个n的数组要O(nlog(n))的时间,排序后就能找到重复的数组。
方法四:

function duplicate(numbers, duplication)
{
    if(numbers == null) return false;
    if(numbers.length <=1) return false;
    for(let i = 0; i<numbers.length; i++){
        while(numbers[i]! = i){
            if(numbers[i] == numbers[numbers[i]]){
                duplication[0] = numbers[i];
                return true;
            }
            let temp = numbers[i];
            numbers[i] = numbers[temp];
            numbers[temp] = temp;
        }
    }
    return false;
}

交换法

二维数组中的查找
边缘检测法,选择右上角或者左下角与target比较

function Find(target, array)
{
    let rows = array.length;
    let columns = array[0].length;
    for(let row = 0, column = columns-1;row<rows && column>=0;){
        if(array[row][column] > target){
            column--;
        }
        else if(array[row][column] < target){
            row ++;
        }else{
            return true;
        }
    }
    return false;
}

面试题 5 替换空格

function replaceSpace(str)
{
    return str.replace(/\s/g,"%20");
}

或者

function replaceSpace(str)
{
    let arr = new Array();
    arr = str.split(" ");
    let output = arr[0];
    for (let i = 1;i<arr.length;i++){
        output = output + "%20"+arr[i];
    }
    return output;
}

剑指offer上的方法,未完成

function replaceSpace(str){
    if(str.length<=0) return;
    let originalLength = str.length;
    let numberOfBlank = 0;
    for(let i = 0; i<str.length;i++){
        if(str[i] == " ") numberOfBlank++;
    }
    let newLength = originalLength + numberOfBlank*2;
    let indexOfOriginal = originalLength;
    let indexOfNew = newLength;
    while(indexOfOriginal>=0 && indexOfNew > indexOfOriginal){
        if(str[indexOfOriginal] == " "){
            str[indexOfNew--] = "0";
            str[indexOfNew--] = "2";
            str[indexOfNew--] = "%";
        }
        else{
            str[indexOfNew--] = str[indexOfOriginal];
        }
        --indexOfOriginal;
    }
    return str;
}

面试6 从尾到头打印链表

前清摘要:
链表是一种动态数据结构,创建链表时,无须知道链表长度,插入一个节点时,只需要为新节点分配内存。每添加一个节点分配一次内存,由于没有闲置内存,链表空间效率比数组高。
链表遍历一次就是O(n),数组是O(1)

\\javascript
function printListFromTailToHead(head)
{
    let arr = new Array();
    let tmp = head;
    while(tmp){
        arr.push(tmp.val);
        tmp = tmp.next;
    }
    let output = arr.reverse();
    return output;
}

使用java 递归处理

import java.util.ArrayList;
public class Solution {
    ArrayList<Integer> mylist  = new ArrayList<Integer>();
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        if(listNode!= null){
            printListFromTailToHead(listNode.next);
            mylist.add(listNode.val);
        }
        return mylist;
    }
}

使用java stack处理

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.Stack;
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        Stack<Integer> mystack = new Stack<Integer>();
        while(listNode != null){
            mystack.push(listNode.val);
            listNode = listNode.next;
        }
        ArrayList<Integer> mylist = new ArrayList<Integer>();
        while(!mystack.isEmpty()){
            mylist.add(mystack.pop());
        }
        return mylist;
    }
}

面试题7 重建二叉树

前清摘要:
树的父节点和子节点之间用指针连接。
二叉树是树的一种特殊结构,在二叉树中每个节点最多只有两个子节点。

前序遍历:先访问根节点,再访问左子节点,最后访问右子节点。
中序遍历:先访问左子节点,再访问根节点,最后访问右子节点。
后序遍历:先访问左子节点,再访问右子节点,最后访问根节点。

二叉搜索树,左节点总是小于等于根节点,右节点总是大于或者等于根节点。平均在O(logn)时间内
二叉树的特例是堆和红黑树,堆分最大堆和最小堆,需要快速找到最大最小值的就用堆来解决。
红黑树把树中节点定义为红黑两色,并通过规则确保,根节点到叶节点最长路径长度不超过最短路径两倍。
javascript第一种方法

/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function reConstructBinaryTree(pre, vin)
{
    if(pre.length<=0 || vin.length<=0)  return null;
    let center = vin.indexOf(pre[0]);
    let left = vin.slice(0,center);//中序左子树
    let right = vin.slice(center+1);//中序右子树
    return{
        val:pre[0],
        left:reConstructBinaryTree(pre.slice(1,center+1), left),
        right:reConstructBinaryTree(pre.slice(center+1), right)
    };
}

java解法

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        TreeNode root = createTree(pre,0,pre.length-1,in,0,in.length-1);
        return root;
    }
    private TreeNode createTree(int []pre,int startpre,int endpre,int []in,int startvin,int endvin){
        if(startpre>endpre||startvin>endvin)
            return null;
        TreeNode root = new TreeNode(pre[startpre]);
        for( int i=startvin; i<=endvin;i++){
            if(in[i]==pre[startpre]){
                root.left = createTree(pre,startpre+1,startpre+i-startvin,in,startvin,i-1);
                root.right = createTree(pre,i-startvin+startpre+1,endpre,in,i+1,endvin);
                break;
            }
        }
        return root;
    }
}

面试题8 二叉树的下一个节点

/*function TreeLinkNode(x){
    this.val = x;
    this.left = null;
    this.right = null;
    this.next = null;
}*/
function GetNext(pNode)
{
    // write code here
    let pnext = null;
    let pparent = pNode.next;
    if(!pNode)return null
    if(pNode.right!=null){
        pnext = pNode.right;
        while(pnext.left){
            pnext = pnext.left;
        }
    }else{
        pnext = pNode.next;
        if(pNode.next && pNode.next.right== pNode){
            while(pnext.next && pnext.next.right==pnext){
                pnext = pnext.next;
            }
            if(pnext.next!=null){
                pnext = pnext.next;
            }else{
                pnext = null;
            }
        }
    }
    return pnext;
}

java解法

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        TreeLinkNode pnext = null;
        if(pNode==null){
            return null;
        }
        if(pNode.right!=null){
            pnext = pNode.right;
            while(pnext.left!=null){
                pnext = pnext.left;
            }
        }else{
            pnext = pNode.next;
            if(pnext!=null && pnext.right==pNode){
                while(pnext.next!=null && pnext.next.right==pNode){
                    pnext = pnext.next;
                }
                if(pnext.next==null){
                    pnext = null;
                }else{
                    pnext= pnext.next;
                }
            }
        }
        return pnext;
    }
}```

## 面试题9,用两个栈实现队列
前清摘要:栈是一个不考虑排序的数据结构,需要O(n)时间才能找到最大和最小的元素
栈先进后出
队列先进先出
javascript实现方法
```javascript
var stack1 = [];
var stack2 = [];
function push(node)
{
    stack1.push(node);
}
function pop()
{
    if(stack2.length==0){
        if(stack1.length==0){
            return null;
        }else{
            for(var i=0;i<stack1.length;i++){
                stack2.push(stack1.pop());
            }
            return stack2.pop();
        }
    }else{
        return stack2.pop();
    }
}

java解法

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        if(stack2.empty()){
            if(stack1.empty()){
                throw new RuntimeException("Queue is empty!");
            }else{
                while(!stack1.empty()){
                    stack2.push(stack1.pop());
                }
                return stack2.pop();
            }
        }else{
            return stack2.pop();
        }
    }
}

面试题10 斐波那契数列

function Fibonacci(n)
{
    if(n < 2){
        return n;
    }else{
        let f0 = 0;
        let f1 = 1
        for(let i=2; i<=n;i++){
            f2 = f1+f0;
            f0 = f1;
            f1 = f2;
        }
    return f2;
    }
}

十分精妙的C语言解法

class Solution {
public:
    int Fibonacci(int n) {
        int f = 0, g = 1;
        while(n--) {
            g += f;
            f = g - f;
        }
        return f;
    }
};

青蛙跳台阶和21格子覆盖28都是斐波那契数列

二分法java

import java.util.*;

public class BinarySearch {
    public int getPos(int[] A, int n, int val) {
        // write code here
        if(n <= 0 || A == null) return -1;
        int start = 0;
        int end = n-1;
        int mid = 0;
        while(end>start){
            mid = (end+start)/2;
            if(A[mid] == val){
                end = mid;
            }else if(A[mid] > val){
                end = mid-1;
            }else{
                start = mid+1;
            }
        }
        if(A[start] == val) return start;
        return -1;
    }
}

java实现快排

public class fastsort{
    public static void main(String[] args) {
        int []arr = {3,4,5,6,1,3,6,7,2,3,5,3,3,1,4,5,34,21,2};
        quicksort(arr);
        for (int i = 0 ;i<arr.length;i++){
            System.out.print(arr[i]+",");
        }
    }
    private static void quicksort(int []arr){
        qsort(arr, 0, arr.length-1);
    }
    private static void qsort(int []arr, int left, int right){
        if(arr == null || arr.length<=0 || left>=right) return;
        int mid = partition(arr, left ,right);
        qsort(arr, left ,mid-1);
        qsort(arr, mid+1, right);
    }

    private static int partition(int []arr, int left, int right){
        int privot= arr[left];
        while(left<right){
            while(left<right && arr[right] >= privot){
                right--;
            }
            arr[left] = arr[right];
            while(left<right && arr[left] <= privot){
                left++;
            }
            arr[right] = arr[left];
        }
        arr[left] = privot;
        return left;
    }
}

面试题11:旋转数组的最小数字

时间太慢

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        int left = 0;
        int right = array.length-1;
        int index = left;
        while(left<right){
            if((right-left) == 1){
                index = right;
                break;
            }else{
                index = (left+right)/2;
                if(array[index]>=array[left]){
                    left = index;
                }
                if(array[index]<=array[right]){
                    right = index;
                }
            }
        }
    return array[index];
    }
}

java 二分法快一点

import java.util.ArrayList;
public class Solution {
    public int minNumberInRotateArray(int [] array) {
        int low = 0;
        int high = array.length-1;
        while(low<high){
            int mid = low+(high - low)/2;
            if(array[mid]>array[high]){
                low = mid + 1;
            }else if(array[mid]==array[high]){
                high = high -1;
            }else if(array[mid]<array[high]){
                high = mid;
            }
        }
    return array[low];
    }
}

面试题12:矩阵中的路径

// 回溯
// 基本思想:
// 0.根据给定数组,初始化一个标志位数组,初始化为false,表示未走过,true表示已经走过,不能走第二次
// 1.根据行数和列数,遍历数组,先找到一个与str字符串的第一个元素相匹配的矩阵元素,进入judge
// 2.根据i和j先确定一维数组的位置,因为给定的matrix是一个一维数组
// 3.确定递归终止条件:越界,当前找到的矩阵值不等于数组对应位置的值,已经走过的,这三类情况,都直接false,说明这条路不通
// 4.若k,就是待判定的字符串str的索引已经判断到了最后一位,此时说明是匹配成功的
// 5.下面就是本题的精髓,递归不断地寻找周围四个格子是否符合条件,只要有一个格子符合条件,就继续再找这个符合条件的格子的四周是否存在符合条件的格子,直到k到达末尾或者不满足递归条件就停止。
// 6.走到这一步,说明本次是不成功的,我们要还原一下标志位数组index处的标志位,进入下一轮的判断。

public class square {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        //标志位,初始化为false
        boolean[] flag = new boolean[matrix.length];
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                 //循环遍历二维数组,找到起点等于str第一个元素的值,再递归判断四周是否有符合条件的----回溯法
                 if(judge(matrix,i,j,rows,cols,flag,str,0)){
                     return true;
                 }
            }
        }
        return false;
    }
     
    //judge(初始矩阵,索引行坐标i,索引纵坐标j,矩阵行数,矩阵列数,待判断的字符串,字符串索引初始为0即先判断字符串的第一位)
    private boolean judge(char[] matrix,int i,int j,int rows,int cols,boolean[] flag,char[] str,int k){
        //先根据i和j计算匹配的第一个元素转为一维数组的位置
        int index = i*cols+j;
        //递归终止条件
        if(i<0 || j<0 || i>=rows || j>=cols || matrix[index] != str[k] || flag[index] == true) //matrix[index] != str[k]当前找到的矩阵值不等于数组对应位置的值,flag[index] == true已经走过的
            return false;
        //若k已经到达str末尾了,说明之前的都已经匹配成功了,直接返回true即可
        if(k == str.length-1)
            return true;
        //要走的第一个位置置为true,表示已经走过了,主程序进入这里终于true了
        flag[index] = true;
         
        //回溯,递归寻找,每次找到了就给k加一,找不到,还原,假设找到了,继续进入下一个judge递归,
        if(judge(matrix,i-1,j,rows,cols,flag,str,k+1) ||
           judge(matrix,i+1,j,rows,cols,flag,str,k+1) ||
           judge(matrix,i,j-1,rows,cols,flag,str,k+1) ||
           judge(matrix,i,j+1,rows,cols,flag,str,k+1)  )
        {
            return true;
        }
        //走到这,说明这一条路不通,还原,再试其他的路径
        flag[index] = false;
        return false;
    }
}

javascript解法

function hasPath(matrix, rows, cols, path)
{
    let lenOfMatrix = matrix.length;
    let flag = new Array(lenOfMatrix);
    for(let i=0;i<rows;i++){
        for(let j=0;j<cols;j++){
            if(judge(matrix, i , j, rows, cols, flag, path, 0))
                return true;
        }
    }
    return false;
}
function judge(matrix, i, j, rows, cols, flag, path, k){
    let index = i * cols + j;
    if( i<0 || j<0 || i>=rows || j>=cols || matrix[index]!= path[k] || flag[index]==true){
        return false;
    }
    flag[index] = true;
    if(k == path.length-1){
        return true;
    }
    if(judge(matrix, i+1, j, rows, cols, flag, path, k+1)||
       judge(matrix, i-1, j, rows, cols, flag, path, k+1)||
       judge(matrix, i, j+1, rows, cols, flag, path, k+1)||
       judge(matrix, i, j-1, rows, cols, flag, path, k+1)){
        return true;
    }
    flag[index] = false;
    return false;
}

面试题13 机器人运动范围

//回溯法,每到一个点继续判定它周围4个点满不满足条件
public class Solution {
    public int movingCount(int threshold, int rows, int cols)
    {
        if(threshold<=0|| rows<=0 ||cols<=0){
            return 0;
        }
        boolean[] visited = new boolean[rows*cols];
        for(int i=0;i<visited.length;i++){
            visited[i] = false;
        }
        int output = countmovement(threshold, rows, cols, 0, 0, visited);
        return output;
    }
    private static int countmovement(int threshold, int rows, int cols, int row, int col,boolean[] visited){
        int index = row*cols+col;
        int count = 0;
        if(check(threshold, rows, cols, row, col, visited)){
            visited[index] = true;
            count = 1+countmovement(threshold, rows, cols, row+1, col, visited)+
                    countmovement(threshold, rows, cols, row-1, col, visited)+
                    countmovement(threshold, rows, cols, row, col+1, visited)+
                    countmovement(threshold, rows, cols, row, col-1, visited);
        }
        return count;
    }
    private static boolean check(int threshold, int rows, int cols,int row, int col, boolean[] visited){
        if(row>=0 && col>=0 && row < rows && col< cols && getsum(col)+getsum(row)<=threshold && !visited[row*cols+col]){
            return true;
        }
        return false;
    }
    private static int getsum(int number){
        int sum = 0;
        while(number > 0){
            sum = sum+number%10;
            number = number/10;
        }
        return sum;
    }
}

面试题14 剪绳子

public class cutstring{
    public static void main(String[] args) {
        int output1 = countsum(348);
        int output2 = countsumFortanxin(348);
        int output3 =  matProductAfterCutting_2(348);
        System.out.println(output1+","+output2+","+output3);
    }
    //动态规划
    private static int countsum (int length){
        if(length<2) return 0;
        if(length == 2) return 1;
        if(length == 3) return 2;
        int[] arr = new int[length+1];
        arr[1] = 1;
        arr[2] = 2;
        arr[3] = 3;
        int max = 0;
        for(int i=4;i<=length;i++){
            max = 0;
            for(int j = 1;j <= i/2;j++){
                int product = arr[j]*arr[i-j];
                if( product > max){
                    max = product;
                }

            }
            arr[i] = max;
        }
        max = arr[length];
        return max;
    }
    //贪心算法,尽量用3乘, 余2就乘4, 余1就乘2
    private static int countsumFortanxin (int length){
        if(length<2) return 0;
        if(length == 2) return 1;
        if(length == 3) return 2; 
        int countFor3 = length/3;// 7除以3余1
        int modFor3 = length % 3;
        int output = 0;
        if(modFor3 == 0){
            output = (int)Math.pow(3, countFor3);
        }else if(modFor3 == 1){
            output = (int)Math.pow(3, countFor3-1)*4;
        }else if(modFor3 == 2){
            output = (int)Math.pow(3, countFor3)*2;
        }
        return output;
    }
    private static int matProductAfterCutting_2(int length) {

        if (length < 2) {
            return 0;
        }
        if (length == 2) {
            return 1;
        }
        if (length == 3) {
            return 2;
        }
        // 当n>=5的时候,尽可能剪长度为3的绳子
        int timeOf3 = length / 3;
        // 当n=4的时候,剪成长度为2的两段
        if (length - timeOf3 * 3 == 1) {
            timeOf3 -= 1;
        }
        // 剪成长度为2的两段
        int timeOf2 = (length - timeOf3 * 3) / 2;
        return (int) ((Math.pow(3, timeOf3)) * (Math.pow(2, timeOf2)));
    }
}

面试题 15 二进制数里有多少1

链接:https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8
来源:牛客网

public class Solution {
    //从n的2进制形式的最右边开始判断是不是1
    /*
    * 该解法如果输入时负数会陷入死循环,
    * 因为负数右移时,在最高位补得是1
    * 二本题最终目的是求1的个数,那么会有无数个
    * 1了。
    */
    //-------------可能陷入死循环的解法---------------------
    public static int NumberOf1_CanNotUse(int n) {
        int count = 0;
        while (n != 0) {
            /*
            * 用1和n进行位与运算,
            * 结果要是为1则n的2进制形式
            * 最右边那位肯定是1,否则为0
            */
            if ((n & 1) == 1) {
                count++;
            }
            //把n的2进制形式往右推一位
            n = n >> 1;
        }
        return count;
    }
    //---------------正解--------------------------------
    //思想:用1(1自身左移运算,其实后来就不是1了)和n的每位进行位与,来判断1的个数
    private static int NumberOf1_low(int n) {
        int count = 0;
        int flag = 1;
        while (flag != 0) {
            if ((n & flag) != 0) {
                count++;
            }
            flag = flag << 1;
        }
        return count;
    }
    //--------------------最优解----------------------------
    public static int NumberOf1(int n) {
        int count = 0;
        while (n != 0) {
            ++count;
            n = (n - 1) & n;
        }
        return count;
    }
    public static void main(String[] args) {
        //使用n=10,二进制形式为1010,则1的个数为2;
        int n = -10;
        System.out.println(n + "的二进制中1的个数:" + NumberOf1(n));
    }
}

面试题16 数值的整数次方

public class Solution {
    public double Power(double base, int exponent) {
        if(exponent<0){
            int absexponent = -exponent;
            return 1.0/count(base,absexponent);
        }else{
            return count(base, exponent);
        }
    }
    private static double count(double base, int exponent){
        double result = 1.0;
        for(int i=0;i<exponent;i++){
            result = result*base;
        }
        return result;
    }
}
\\用递归算法做
public class Solution {
    public double Power(double base, int exponent) {
        if(exponent == 0) return 1;
        if(exponent == 1) return base;
        int absexponent = Math.abs(exponent);
        double result = Power(base, absexponent/2);
        result = result * result;
        if(absexponent % 2 == 1){
            result = result * base;
        }
        if(exponent<0){
            return 1.0/result;
        }else{
            return result;
        }
    }
}

面试题 17 从1 打印到n

https://blog.youkuaiyun.com/u013132035/article/details/80563507
常规解法:一步步注意手写演算,很巧妙
递归解法: 一步步注意手写演算,很巧妙。每次进位时都会回到第一个函数中的for循环,注意先用n=2 ,[][]来尝试。

面试题 18删除链表节点

//把第j个节点的值复制给第i个
 private void delete(ListNode head, ListNode tobedeleted){
        if(head == null || tobedeleted == null){
            return;
        }
        if(tobedeleted.next != null){
            tobedeleted.val = tobedeleted.next.val;
            tobedeleted.next = tobedeleted.next.next;
        }else if(head == tobedeleted){
            head = null;
            tobedeleted = null;
        }else{
            ListNode tmp = head;
            while(tmp.next != null){
                tmp = tmp.next;
            }
            tmp.next = null;
            tobedeleted = null;
        }
    }

删除重复链表节点(没懂)

public static ListNode deleteDuplication(ListNode pHead) {
         
        ListNode first = new ListNode(-1);//设置一个trick
 
        first.next = pHead;
 
        ListNode p = pHead;
        ListNode last = first;
        while (p != null && p.next != null) {
            if (p.val == p.next.val) {
                int val = p.val;
                while (p!= null&&p.val == val)
                    p = p.next;
                last.next = p;
            } else {
                last = p;
                p = p.next;
            }
        }
        return first.next;
    }
//沁岩的做法,递归很容易懂。
/*
 public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}
*/
// created by lqy niubility
public class Solution {
    public ListNode deleteDuplication(ListNode pHead)
    {   
        if(pHead==null)return null;
        if(pHead.next==null)return pHead;
         // 只有0个或1个结点,则返回
        int val=pHead.val;
        ListNode ln=pHead.next;
        if(val!=ln.val){
            pHead.next=deleteDuplication(ln);// 保留当前结点,从下一个结点开始递归
            return pHead;
        }else{
            while(ln!=null && val==ln.val){
            // 跳过值与当前结点相同的全部结点,找到第一个与当前结点不同的结点
                ln=ln.next;
            }
        return deleteDuplication(ln); // 从第一个与当前结点不同的结点开始递归
    }
}
}

面试题 20 表达数值的字符串

public class Solution {
    public boolean isNumeric(char[] str) {
        boolean sign = false;
        boolean decimal = false;
        boolean hasE = false;
        for(int i = 0;i< str.length;i++){
            if(str[i] == 'e' || str[i] == 'E'){
                if (i == str.length-1) return false;//e后面一定要跟着数字
                if (hasE) return false; //不能有两个e
                hasE = true;
            }else if(str[i] == '+' || str[i] == '-'){
                if( sign && str[i-1] !='e' && str[i-1] != 'E') return false;
                // 第二次出现+必须紧跟在e后面
                if(!sign && i>0 && str[i-1]!='e' && str[i-1]!='E') return false;
                // 第一次出现+的话,非开头,也必须跟在e后面
                sign = true;
            }
            else if(str[i]=='.'){
                if (hasE || decimal) return false;
                //e后面不能接小数,小数点不能出现两次
                decimal = true;
            }else if(str[i] < '0' || str[i] > '9'){ //不合法字符
                return false;
            }
         }
        return true;
    }
}

正则解法,看我另外一篇原创 https://blog.youkuaiyun.com/weixin_39285712/article/details/89926985

调正数组顺序奇数在偶数前面

//建立两个数组,空间换时间
function reOrderArray(array)
{
    // write code here
    let even = [];
    let old = [];
    for(let i = 0;i<array.length;i++){
        if(isEven(array[i])){
            even.push(array[i]);
        }else{
            old.push(array[i]);
        }
    }
    for(let j = 0;j<even.length;j++){
        old.push(even[j]);
    }
    return old;
}
function isEven(num){
    if(num % 2 ==0)
        return true;
}
//剑指offer做法,前后两个指针。
public class Solution {
    public void reOrderArray(int [] array) {
        int i = 0;
        int j = array.length-1;
        while(i < j){
            while(i< j && array[i] % 2 == 1){
                i++;
            }
            while (i<j && array[j] % 2 == 0){
                j--;
            }
            if(i < j){
                int tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
            }
        }           
    }
}
//冒泡做法
public class Solution {
    public void reOrderArray(int [] array) {
        for(int i=0;i<array.length-1;i++){
            for(int j=0;j<array.length-1-i;j++){
                if((array[j]%2)== 0 && (array[j+1]%2)==1){
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }          
        }
    }
}

鲁棒性:啥叫鲁棒型就是不管程序在什么情况,什么输入,什么网络下都不会崩溃。特别是奇奇怪怪的输入。

链表中倒数第k个节点

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head == null) return null;
        if(k == 0) return null;
        ListNode first = head;
        ListNode second = null;
        for(int i = 0;i<k-1;i++){
            if(first.next != null){
                first = first.next;
            }else{
                return null;
            }
        }
        second = head;
        while(first.next != null){
            first = first.next;
            second = second.next;
        }
        return second;
    }
}

反思,当我们用一个指针不能解决的问题可以考虑用两个指针遍历链表。可以让一个指针走的快一点。
比如求中间节点的链表题,可以让一个指针走两步,另一个走一步。

面试题 23 :链表中环的入口节点

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        ListNode meetingnode = meetnode(pHead);
        int count = 1;
        if(meetingnode == null) return null;
        ListNode p1= meetingnode;
        while(p1.next != meetingnode){
            p1 = p1.next;
            count++;
        }
        ListNode first = pHead;
        ListNode second = pHead;
        for(int j=0;j<count;j++){
            first = first.next;
        }
        while(first != second){
            first = first.next;
            second = second.next;
        }
        return second;
    }
    private static ListNode meetnode(ListNode head){
        if(head == null) return null;
        if(head.next == null) return null;
        ListNode slow = head.next;
        ListNode fast = slow.next;
        while(fast != null && slow != null){
            if(fast == slow) return fast;
            fast = fast.next;
            slow = slow.next;
            if(fast != slow){
                fast = fast.next;
            }
        }
        return null;
    }
}

面试题 24反转链表

//我们需要设置三个指针来保存前中后三个节点。
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head == null) return null;
        if(head.next == null) return head;
        ListNode pnext = head;
        ListNode pbefore = null;
        ListNode pafter = null;
        ListNode preversehead = null;
        while(pnext != null){
            pafter = pnext.next;
            if(pafter == null) preversehead = pnext;
            pnext.next = pbefore;
            pbefore = pnext;
            pnext = pafter;
        }
        return preversehead;
    }
}

面试题 25 合并两个有序链表

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
    ListNode tmp = new ListNode(20);
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        ListNode mergednode = null;
        ListNode current = null;
        while(list1!=null && list2 !=null){
            if(list1.val > list2.val){
                if(mergednode == null) {
                    mergednode = current = list2;
                }else{
                    current.next = list2;
                    current = current.next;
                }
                list2 = list2.next;
            }else{
                if(mergednode == null) {
                    mergednode = current= list1;
                }else{
                    current.next = list1;
                    current = current.next;
                }
                list1 = list1.next;
            }
        }
        if(list1 == null){
            current.next = list2;
        }else{
            current.next = list1;
        }
        return mergednode;
    }
}
//递归算法
/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
    ListNode tmp = new ListNode(20);
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        if(list1.val > list2.val){
            list2.next = Merge(list1, list2.next);
            return list2;
        }else{
            list1.next = Merge(list1.next, list2);
            return list1;
        }
    }
}

面试题26 树的子结构

//用递归来做
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean result = false;
        if(root1 == null || root2 == null) return false;
        if(root1.val == root2.val){
            result = DoesTree2likeTree2 (root1,root2);
        }
        if(!result){
            result = HasSubtree(root1.left, root2);
        }
        if(!result){
            result = HasSubtree(root1.right, root2);
        }
        return result;
    }
    private boolean DoesTree2likeTree2 (TreeNode root1, TreeNode root2){
        if(root2 == null) return true;
        if(root1 == null) return false;
        if(root1.val != root2.val){
            return false;
        }
        return DoesTree2likeTree2(root1.left, root2.left) && DoesTree2likeTree2(root1.right, root2.right);
    }
}

面试题 二叉树的镜像

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public void Mirror(TreeNode root) {
        if(root == null) return;
        if(root.left == null && root.right == null) return;
        TreeNode  tmp = root.left;
        root.left = root.right;
        root.right = tmp;
        if(root.right != null){
            Mirror(root.right);
        }
        if(root.left != null){
            Mirror(root.left);
        }
    }
}
/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function Mirror(root)
{
    // write code here
    if(root == null) return;
    if(root.left == null && root.right == null) return;
    let tmp = root.left;
    root.left = root.right;
    root.right = tmp;
    if(root.right != null){
        Mirror(root.right);
    }
    if(root.left != null){
        Mirror(root.left);
    }
}

面试题28 对称的二叉树

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    boolean isSymmetrical(TreeNode pRoot)
    {
        return isSymmetrical(pRoot, pRoot);
    }
    private boolean isSymmetrical(TreeNode pRoot1, TreeNode pRoot2){
        if(pRoot1 == null && pRoot2 == null) return true;
        if(pRoot1 == null || pRoot2 == null) return false;
        if(pRoot1.val != pRoot2.val ) return false;
        return isSymmetrical(pRoot1.left, pRoot2.right) && isSymmetrical(pRoot1.right, pRoot2.left);
    }
}

面试题29 顺时针打印矩阵

这道题就是找规律,首先确定layer层数,就是找规律看绕几圈。注意三个break就是在特殊情况下不能继续画圈圈。

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
       ArrayList<Integer> result = new ArrayList<Integer>();
       if(matrix.length == 0) return result;//如果矩阵行数为0,说明是空矩阵,则直接返回空列表
       int columns = matrix[0].length;
       int rows = matrix.length;
       if(columns == 0) return result; //如果矩阵行数不为0,矩阵的列数为0,意味着矩阵由空元素组成,依然返回空列表
       int layers = (Math.min(columns, rows)-1)/2+1;
       for(int i=0;i<layers;i++){
           for(int k = i; k< columns-i;k++){
               result.add(matrix[i][k]);
           }
           if(i+1>rows-1-i) break;
           for(int k = i+1; k< rows-i;k++){
               result.add(matrix[k][columns-1-i]);
           }
           if(columns-2-i<0) break;
           for(int k = columns-2-i; k>=i;k--){
               result.add(matrix[rows-1-i][k]);
           }
           if(rows-2-i<0) break;
           for(int k = rows-2-i; k>i;k--){
               result.add(matrix[k][i]);
           }
       }
       return result;
    }
}
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
       ArrayList<Integer> result = new ArrayList<Integer>();
       if(matrix.length == 0) return result;
       int columns = matrix[0].length;
       int rows = matrix.length;
       if(columns == 0) return result;
       int left = 0;
       int right = columns-1;
       int top = 0;
       int bottom = rows-1;
       while (left <= right && top <= bottom)
        {
            // left to right
            for (int i = left; i <= right; ++i)  result.add(matrix[top][i]);
            // top to bottom
            for (int i = top + 1; i <= bottom; ++i)  result.add(matrix[i][right]);
            // right to left
            for (int i = right - 1; i >= left&&top<bottom; --i)  result.add(matrix[bottom][i]);
            // bottom to top
            for (int i = bottom - 1; i > top&&right>left; --i)  result.add(matrix[i][left]);
            left++;
            top++;
            right--;
            bottom--;
        }
       return result;
    }
}

面试题30 包含min函数 的栈

import java.util.Stack;
 
public class Solution {
    Stack<Integer> mainstack = new Stack<Integer>();
    Stack<Integer> tmpstack = new Stack<Integer>();
    public void push(int node) {
        mainstack.push(node);
        if(tmpstack.isEmpty()){
            tmpstack.push(node);
        }else if(node < tmpstack.peek()){ //只有当数字小于辅助栈顶端数字时才push
            tmpstack.push(node);
        }
    }
     
    public void pop() {
        if(tmpstack.peek()==mainstack.peek()) //只有当两个栈顶端数字相同时才pop
            tmpstack.pop();
        mainstack.pop();
        
    }
     
    public int top() {
        return mainstack.peek();
    }
     
    public int min() {
        return tmpstack.peek();
    }
}

面试题31 栈的压入弹出序列

摘选自 https://www.nowcoder.com/profile/844008/codeBookDetail?submissionId=1522453
思路】借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
举例:
入栈1,2,3,4,5
出栈4,5,3,2,1
首先1入辅助栈,此时栈顶1≠4,继续入栈2
此时栈顶2≠4,继续入栈3
此时栈顶3≠4,继续入栈4
此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3
此时栈顶3≠5,继续入栈5
此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3

….

依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。

import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        if(pushA.length == 0 || popA.length == 0)
            return false;
        Stack<Integer> s = new Stack<Integer>();
        //用于标识弹出序列的位置
        int popIndex = 0;
        for(int i = 0; i< pushA.length;i++){
            s.push(pushA[i]);
            //如果栈不为空,且栈顶元素等于弹出序列
            while(!s.empty() &&s.peek() == popA[popIndex]){
                //出栈
                s.pop();
                //弹出序列向后一位
                popIndex++;
            }
        }
        return s.empty();
    }
}

面试题32 打印二叉树

//使用二叉树
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        ArrayList<Integer> result = new ArrayList<>();
        if(root == null) return result;
        queue.offer(root);
        while(!queue.isEmpty()){
            TreeNode tmp = queue.poll();
            result.add(tmp.val);
            if(tmp.left!=null) queue.offer(tmp.left);
            if(tmp.right!=null) queue.offer(tmp.right);
        }
        return result;
    }
}

分行打印二叉树

https://blog.youkuaiyun.com/qq1263292336/article/details/76168094

之字型打印二叉树

链接:https://www.nowcoder.com/questionTerminal/91b69814117f4e8097390d107d2efbe0
来源:牛客网
设立两个栈,打印一个栈里节点时,它的子节点放在另一个栈里,当一层所有节点打印完毕时,交换这两个栈并继续下一个层。
public static ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        int layer = 1;
        //s1存奇数层节点
        Stack<TreeNode> s1 = new Stack<TreeNode>();
        s1.push(pRoot);
        //s2存偶数层节点
        Stack<TreeNode> s2 = new Stack<TreeNode>();
         
        ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
         
        while (!s1.empty() || !s2.empty()) {
            if (layer%2 != 0) {
                ArrayList<Integer> temp = new ArrayList<Integer>();
                while (!s1.empty()) {
                    TreeNode node = s1.pop();
                    if(node != null) {
                        temp.add(node.val);
                        System.out.print(node.val + " ");
                        s2.push(node.left);
                        s2.push(node.right);
                    }
                }
                if (!temp.isEmpty()) {
                    list.add(temp);
                    layer++;
                    System.out.println();
                }
            } else {
                ArrayList<Integer> temp = new ArrayList<Integer>();
                while (!s2.empty()) {
                    TreeNode node = s2.pop();
                    if(node != null) {
                        temp.add(node.val);
                        System.out.print(node.val + " ");
                        s1.push(node.right);
                        s1.push(node.left);
                    }
                }
                if (!temp.isEmpty()) {
                    list.add(temp);
                    layer++;
                    System.out.println();
                }
            }
        }
        return list;
    }

33 二叉树后序遍历

用递归,最后一位是根节点,前半部是左子树,右半边是右子树,右子树不能出现小于根节点的树。
public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        if(sequence.length == 0) return false;
        return isBST(sequence, 0 , sequence.length-1);
    }
    private static boolean isBST(int [] sequence, int start, int end){
        if(end<=start) return true;
        int root = sequence[end];
        int i = start;
        for(;i<end;i++){
            if(sequence[i]>root){
                break;
            }
        }
        for(int j=i;j<end;j++){
            if(sequence[j]<root){
                return false;
            }
        }
        return isBST(sequence,start,i-1) && isBST(sequence,i, end-1);
    }
}

34 二叉树中和为某一值的路径

import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    ArrayList<ArrayList<Integer>> allpath = new ArrayList<>();
    ArrayList<Integer> path = new ArrayList<>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        if(root == null) return allpath;
        path.add(root.val);
        target = target - root.val;//现在target变成这个了
        if(root.left == null && root.right == null && target == 0){
            allpath.add(new ArrayList<Integer>(path));//假如没有叶子节点并且target为0,添加进allpath
            //为啥要新建构造函数,否则后面list.add和list.remove都是改变应用,会影响原来的list.
        }
        FindPath(root.left, target);
        FindPath(root.right, target);
        path.remove(path.size()-1);//无论是不是匹配都要删除最后一个回退
        return allpath;
    }
}

35 复杂链表的复制

36 二叉搜索树与双向链表

https://www.nowcoder.com/profile/163334/codeBookDetail?submissionId=1515508
方法一:非递归版
解题思路:
1.核心是中序遍历的非递归算法。
2.修改当前遍历节点与前一遍历节点的指针指向。

    import java.util.Stack;
    public TreeNode ConvertBSTToBiList(TreeNode root) {
        if(root==null)
            return null;
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode p = root;
        TreeNode pre = null;// 用于保存中序遍历序列的上一节点
        boolean isFirst = true;
        while(p!=null||!stack.isEmpty()){
            while(p!=null){
                stack.push(p);
                p = p.left;
            }
            p = stack.pop();
            if(isFirst){
                root = p;// 将中序遍历序列中的第一个节点记为root
                pre = root;
                isFirst = false;
            }else{
                pre.right = p;
                p.left = pre;
                pre = p;
            }      
            p = p.right;
        }
        return root;
    }

方法二:递归版
解题思路:
1.将左子树构造成双链表,并返回链表头节点。
2.定位至左子树双链表最后一个节点。
3.如果左子树链表不为空的话,将当前root追加到左子树链表。
4.将右子树构造成双链表,并返回链表头节点。
5.如果右子树链表不为空的话,将该链表追加到root节点之后。
6.根据左子树链表是否为空确定返回的节点。

    public TreeNode Convert(TreeNode root) {
        if(root==null)
            return null;
        if(root.left==null&&root.right==null)
            return root;
        // 1.将左子树构造成双链表,并返回链表头节点
        TreeNode left = Convert(root.left);
        TreeNode p = left;
        // 2.定位至左子树双链表最后一个节点
        while(p!=null&&p.right!=null){
            p = p.right;
        }
        // 3.如果左子树链表不为空的话,将当前root追加到左子树链表
        if(left!=null){
            p.right = root;
            root.left = p;
        }
        // 4.将右子树构造成双链表,并返回链表头节点
        TreeNode right = Convert(root.right);
        // 5.如果右子树链表不为空的话,将该链表追加到root节点之后
        if(right!=null){
            right.left = root;
            root.right = right;
        }
        return left!=null?left:root;       
    }

方法三:改进递归版
解题思路:
思路与方法二中的递归版一致,仅对第2点中的定位作了修改,新增一个全局变量记录左子树的最后一个节点。
// 记录子树链表的最后一个节点,终结点只可能为只含左子树的非叶节点与叶节点

   protected TreeNode leftLast = null;
   public TreeNode Convert(TreeNode root) {
       if(root==null)
           return null;
       if(root.left==null&&root.right==null){
           leftLast = root;// 最后的一个节点可能为最右侧的叶节点
           return root;
       }
       // 1.将左子树构造成双链表,并返回链表头节点
       TreeNode left = Convert(root.left);
       // 3.如果左子树链表不为空的话,将当前root追加到左子树链表
       if(left!=null){
           leftLast.right = root;
           root.left = leftLast;
       }
       leftLast = root;// 当根节点只含左子树时,则该根节点为最后一个节点
       // 4.将右子树构造成双链表,并返回链表头节点
       TreeNode right = Convert(root.right);
       // 5.如果右子树链表不为空的话,将该链表追加到root节点之后
       if(right!=null){
           right.left = root;
           root.right = right;
       }
       return left!=null?left:root;       
   }

37 字符串的序列化

前序排列,递归,碰到节点为null的时候输出“#“,反向序列的时候也是”1,2,4,#,#,#,#,5,#,8,#“

/*
public class TreeNode {
   int val = 0;
   TreeNode left = null;
   TreeNode right = null;

   public TreeNode(int val) {
       this.val = val;

   }
}
*/
public class Solution {
   String Serialize(TreeNode root) {
       if(root == null) return "";
       StringBuilder sb = new StringBuilder();
       Serialize2(root, sb);
       return sb.toString();
 }
   void Serialize2 (TreeNode root,StringBuilder sb){
       if(root == null){
           sb.append("#,");
           return;
       }
       sb.append(root.val);
       sb.append(",");
       Serialize2(root.left,sb);
       Serialize2(root.right,sb);
   }
   int index = -1;
   TreeNode Deserialize(String str) {
      if (str.length() == 0) return null;
      String[] str1 = str.split(",");
      return Deserialize2(str1);
 }
   TreeNode Deserialize2(String[] str){
       index++;
       if(!str[index].equals("#")){
           TreeNode root = new TreeNode(0);
           root.val = Integer.parseInt(str[index]);
           root.left = Deserialize2(str);
           root.right = Deserialize2(str);
           return root;
       }
       return null;
   }
}

38 字符串的排列

import java.util.ArrayList;
import java.util.Collections;
public class Solution {
    public ArrayList<String> Permutation(String str) {
       ArrayList<String> res = new ArrayList<>();
       //nowcoder上用list,这里用arraylist就可以了
        if(str.length() == 0) 
            return res;
        char[] arrstr = str.toCharArray();
        Permutation1(arrstr, 0 , res);
        Collections.sort(res);//排序不然会出错
        return res;
    }
    public void Permutation1(char[] str , int i , ArrayList<String> res){
        if(i == str.length-1){
            if(!res.contains(new String(str))){ //把字符数组变成字符串
                res.add(new String(str));
                return;
            }
        }else{
            for(int j=i;j < str.length;j++){
            //最外层循环是交换第一个与后面每个元素
                swap(str,i,j);
                Permutation1(str, i+1, res);
                swap(str,i,j);  //第二次交换是为了把之前交换回去的换回来
            }
        }
    }
    public void swap(char[] str, int a, int b){
        char tmp = str[a];
        str[a] = str[b];
        str[b] = tmp;
    }
}

39 数组中超过一半的数字

//首先进行排序,然后超过一般数字肯定就是中位数,然后验证它的数量是不是超过了一半多
import java.util.Arrays;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        Arrays.sort(array);
        int result = array[array.length/2];
        int times = 0;
        for(int i = 0; i< array.length;i++){
            if(array[i] == result) times++;
        }
        if(times*2 <= array.length){
            return 0;
        }else{
            return result;
        }
    }
}
//javascript 除以2需要用 math.floor手动向下取整
function MoreThanHalfNum_Solution(numbers)
{
    // write code here
    numbers.sort();
    let result = numbers[Math.floor(numbers.length/2)];
    let times = 0;
    for(let i = 0; i< numbers.length;i++){
        if(numbers[i] == result) times++;
    }
    if(times*2 <= numbers.length){
        return 0;
    }else{
        return result;
    }
}
//一种很巧妙的方法,我们要找的数字他的数量比其他数字加起来还多,所以最后一次把次数设置为1的数字就是我们要找的数字。
import java.util.Arrays;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        if(array.length == 0 ) return 0;
        int time2 = 1;
        int result2 = array[0];
        for(int j=1; j< array.length;j++){
            if(time2 ==0){
                time2 = 1;
                result2 = array[j];
            }else if(array[j] == result2){
                time2++;
            }else {
                time2--;
            }
        }
        
        int times = 0;
        for(int i = 0; i< array.length;i++){
            if(array[i] == result2) times++;
        }
        if(times*2 <= array.length){
            return 0;
        }else{
            return result2;
        }
    }
}

40 最小的K个数字

//最简单的做法,排序
import java.util.Arrays;
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> res = new ArrayList<Integer>();
        if(k>input.length) return res;
        Arrays.sort(input);
        for(int i=0;i<k;i++){
            res.add(input[i]);
        }
        return res;
    }
}
//冒泡做法,只需要外面循环k次
import java.util.Arrays;
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> res = new ArrayList<Integer>();
        if(k>input.length) return res;
        for(int i = 0; i<k;i++){
            for(int j = 0;j<input.length-1-i;j++){
                if(input[j]<input[j+1]){
                    int tmp = input[j];
                    input[j] = input[j+1];
                    input[j+1] = tmp;
                }
            }
            res.add(input[input.length-i-1]);
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值