剑指offer 21~30

21.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

import java.util.*;
public class Solution {
   public boolean IsPopOrder(int [] pushA,int [] popA) {
       if(pushA.length != popA.length){
           return false;
       }
       Stack<Integer> s = new Stack<>();
       int j = 0;
       for(int i = 0;i < pushA.length; i++){
           s.push(pushA[i]);
           while(!s.isEmpty() && s.peek() == popA[j]){
               s.pop();
               j++;
           }
       }
       return s.isEmpty();
   }
}

思路: 新建一个栈,将数组A压入栈中,当栈顶元素等于数组B时,就将其出栈,当循环结束时,判断栈是否为空,若为空则返回true.

22.从上往下打印出二叉树的每个节点,同层节点从左至右打印。

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if(root == null){
            return list;
        }
        ArrayList<TreeNode> queue = new ArrayList<>();
        TreeNode tmp = null;
        queue.add(root);
        while(!queue.isEmpty()){
            tmp = queue.remove(0);
            if(tmp.left != null){
                queue.add(tmp.left);
            }
            if(tmp.right != null){
                queue.add(tmp.right);
            }
            list.add(tmp.val);
        }
        return list;
    }
}

思路: 建立两个链表,放入一个存放节点,一个存放值.

23.输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路: BST 树就是 左节点 < 根节点 < 右节点 , 后序的特点就是,最后一个为根节点,那么,BST树的后续特点就是 (左子树) (右子树) (根);那么根据根节点的大小,可以找出左子树区间和右子树区间,区间内也满足这个特点.

public class Solution {
    public boolean VerifySquenceOfBST(int [] arr) {
        if(arr.length == 0 || arr == null){
            return false;
        }
        return isBST(arr,0,arr.length - 1);
    }
    
    public boolean isBST(int[] arr,int start,int root){
        if(start >= root){//知道遍历到叶子节点
            return true;
        }
        int rootval = arr[root];
        int i ;
        for(i = start;i < root;i++){//此循环找到左子树区间
            if(arr[i] > rootval){
                break;
            }
        }
        for(int j = i ;j < root;j++){//判断右子树是否大于根节点的大小
            if(arr[j] < rootval){
                return false;
            }
        }
        return isBST(arr,start,i-1)&&isBST(arr,i,root-1);
    }
}

24.输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

import java.util.ArrayList;
public class Solution {
    ArrayList<ArrayList<Integer>> list = new ArrayList<>();
    ArrayList<Integer> path = new ArrayList<>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,//int target) {
        if(root == null){
            return list;
        }
        path.add(root.val);
        target -= root.val;
        if(target == 0 && root.left == null && root.right == null){
        //这里new一个新的目的就是 这个 path 是一个引用,你后面的操作会影响到这个path,自始至终只有一个path,
	//new ArrayList<Integer>(path)就相当于在堆中复制了一个新的;
            list.add(new ArrayList<Integer>(path));
        }
        FindPath(root.left,target);
        FindPath(root.right,target);
        //这个操作就是删除最后一个节点值,要看懂这个操作,就得熟悉递归的过程
        path.remove(path.size() - 1);
        return list;
    }
}

下面我写一个类似的简单的递归过程


public class Solution {
    public static void main(String[] args) {
        fin(3);
    }
    private static void  fin(int a) {
        if (a < 1){
            System.out.println("归");
            return ;
        }
        System.out.println("111 递 " + a);
        fin(a-1);
        System.out.println("222 递 " + a);
        fin(a-2);
        System.out.println("333 归 " + a);
        return ;
    }
}

然后来看看这段代码的运行过程

1113
1112
111122213331
22223332
2223
111122213331
3333

25.输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路: 在这里插入图片描述

/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    public RandomListNode Clone(RandomListNode pHead){
        if(pHead == null){
            return null;
        }
        //第一步
        RandomListNode tmp = pHead;
        while(tmp != null){
            RandomListNode clone = new RandomListNode(tmp.label);
            clone.next = tmp.next;
            tmp.next = clone;
            tmp = clone.next;
        }
        //第二步
        tmp = pHead;
        while(tmp != null){
            tmp.next.random = tmp.random == null ? null : tmp.random.next;
            tmp = tmp.next.next;
        }
        //第三步
        tmp = pHead;
        RandomListNode head = pHead.next;
        RandomListNode node = head;
        while(tmp != null){
            node = tmp.next;
            tmp.next = node.next;
            tmp = node.next;
            node.next = tmp == null ? null:tmp.next;
        }
        return head;
    }
}

26.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

public class Solution {
    TreeNode node = null;
    TreeNode head = null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        cover(pRootOfTree);
        return head;
    }
    public void cover (TreeNode root){
        if(root == null){
            return;
        }
        cover(root.left);
        if(node == null){
            node = root;
            head = root;
        }else{
            node.right = root;
            root.left = node;
            node = root;
        }
        cover(root.right);
        return;
    }
}

27.输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

import java.util.*;
public class Solution {
    ArrayList<String> list = new ArrayList<>();
    public ArrayList<String> Permutation(String str) {
        if(str == null){
            return list;
        }
        sort(str,new StringBuffer());
        return list;
    }
    public void sort(String str,StringBuffer sb){
        if(str.length() == 1){
            sb.append(str.charAt(0));
            int i = list.indexOf(sb.toString());
            if(i == -1){
                list.add(sb.toString());
            }
            return;
        }
        for(int i = 0;i < str.length() ;i++){
            StringBuffer newSB = new StringBuffer();
            newSB.append(sb.toString());
            newSB.append(str.charAt(i));
            sort(str.replaceFirst(String.valueOf(str.charAt(i)),""),newSB);
        }
    }
}

28.数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

import java.util.*;
public class Solution {
    public int MoreThanHalfNum_Solution(int [] array) {
        Arrays.sort(array);
        int num = array[array.length/2];
        int count = 0;
        for(int i : array){
            if(num == i){
                count++;
            }
        }
        if(count > array.length/2){
            return num;
        }
        return 0;
    }
}

29.输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

import java.util.*;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> list = new ArrayList<>();
        if(k > input.length || k == 0){
            return list;
        }
        Arrays.sort(input);
        for(int i = 0;i < k;i++){
            list.add(input[i]);
        }
        return list;
    }
}

30.HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        int max = array[0];
        int res = array[0];
        for(int i = 1;i < array.length;i++){
            max = Math.max(max + array[i],array[i]);
            res = Math.max(max,res);
        }
        return res;
    }
}
发布了42 篇原创文章 · 获赞 13 · 访问量 6508

猜你喜欢

转载自blog.csdn.net/weixin_43508555/article/details/104379723