剑指offer 1-5

1二维数组的查找:

  在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

 

一、暴力法

时间复杂度:
空间复杂度:O(1)

二、从左下找

利用该二维数组的性质:

  • 每一行都按照从左到右递增的顺序排序,
  • 每一列都按照从上到下递增的顺序排序

改变个说法,即对于左下角的值 m,m 是该行最小的数,是该列最大的数
每次将 m 和目标值 target 比较:

  1. 当 m < target,由于 m 已经是该行最大的元素,想要更大只有从列考虑,取值右移一位
  2. 当 m > target,由于 m 已经是该列最小的元素,想要更小只有从行考虑,取值上移一位
  3. 当 m = target,找到该值,返回 true

用某行最小或某列最大与 target 比较,每次可剔除一整行或一整列

时间复杂度:
空间复杂度:O(1)

//二维数组的查找
public class theSeekOfTwodDmensionalArray {

    public static void main(String[] args) {
        theSeekOfTwodDmensionalArray seek = new theSeekOfTwodDmensionalArray();
        int target = 12;
        int[][] array = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
        boolean flag = seek.Find(target, array);
        System.out.println(flag);
    }
     public boolean Find(int target, int [][] array) {
         boolean flag = false;
         int row = array.length-1;
         int col = 0;
         while(row >= 0 && col <=array[0].length-1) {
             if(array[row][col] < target) {
                 col++;
             }else if(array[row][col] > target) {
                 row--;
             }else {
                 return true;
         }
     }
         return false;
}
}

2替换空格

  请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

一、在当前字符串上进行替换。

  1. 先计算替换后的字符串需要多大的空间,并对原字符串空间进行扩容;
  2. 从后往前替换字符串的话,每个字符串只需要移动一次;
  3. 如果从前往后,每个字符串需要多次移动,效率较低
  4. 时间复杂度:O(length) 只遍历了一遍字符串
    空间复杂度:O(1) 没有开辟空间

 

 

public class Solution {
   public static String replaceSpace(StringBuffer s) {
        int count=0;
        int length=s.length();
       //统计空格数量
        for(int i=0;i<length;i++){
            if(s.charAt(i)==' '){
                count++;
            }
        }
       //新长度
        int newLength=length+count*2-1;
       s.setLength(newLength+1);
       //从后往前
        for(int i=length-1;i>=0;i--){
            if(s.charAt(i)==' '){
                s.setCharAt(newLength--,'0');
                s.setCharAt(newLength--,'2');
                s.setCharAt(newLength--,'%');
            }else{
                s.setCharAt(newLength--,s.charAt(i));
            }
        }
       return s.toString();
    }
}

 

 

 

  二、调用自带函数

  三、用新的數組存

当遇到 " ",就追加 "%20",否则遇到什么追加什么

public class replaceSpaceTest {

    public static void main(String[] args) {
        replaceSpaceTest replacespace = new replaceSpaceTest();
        String str = "dog is animal";
        StringBuffer stringbuffer = new StringBuffer(str);
        String s = replacespace.replaceSpace(stringbuffer);
        System.out.println(s);
    }
        //调用库函数
    public String replaceSpace1(StringBuffer str) {
                return str.toString().replace(" ", "%20");
            }
        //追加
    public String replaceSpace(StringBuffer str) {
        StringBuilder stringbuilder = new StringBuilder();
        for(int i =0; i < str.length();i++) {
            if(str.charAt(i) == ' ') {
                stringbuilder.append("%20");
            }else {
                stringbuilder.append(str.charAt(i));
            }
        }
        return stringbuilder.toString();
    }

}

3从尾到头打印链表

  输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

使用ArrayList的add(index,value)

时间复杂度:
空间复杂度:

 

package list;

import java.util.ArrayList;
import java.util.Scanner;

public class printListFromTailToHeadTest {

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        ListNode l = new ListNode(-1);
        ListNode l1 = l;
        while (!s.hasNext("!")) {
            l1.next = new ListNode(s.nextInt());
            l1 = l1.next;
        }
        ArrayList<Integer> res = printListFromTailToHead(l.next);
        System.out.println(res.toString());
    }

    public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer> list = new ArrayList<>();
        while (listNode != null) {
            list.add(0, listNode.val);
            listNode = listNode.next;
        }
        return list;
    }

}

class ListNode {
    int val;
    ListNode next;

    public ListNode(int val) {
        this.val = val;
    }
}

 

import java.util.ArrayList;
//使用递归实现
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        if(listNode==null)return list;
        print(listNode);
        return list;
    }
      ArrayList<Integer> list=new ArrayList<>();
    public void print(ListNode listNode){
        if(listNode!=null){
            if(listNode.next!=null){
                print(listNode.next);
            }
        }
        list.add(listNode.val);
    }
}

 

4重建二叉树

根据中序遍历和前序遍历可以确定二叉树,具体过程为:

  1. 根据前序序列第一个结点确定根结点
  2. 根据根结点在中序序列中的位置分割出左右两个子序列
  3. 对左子树和右子树分别递归使用同样的方法继续分解

例如:
前序序列{1,2,4,7,3,5,6,8} = pre
中序序列{4,7,2,1,5,3,8,6} = in

    1. 根据当前前序序列的第一个结点确定根结点,为 1
    2. 找到 1 在中序遍历序列中的位置,为 in[3]
    3. 切割左右子树,则 in[3] 前面的为左子树, in[3] 后面的为右子树
    4. 则切割后的左子树前序序列为:{2,4,7},切割后的左子树中序序列为:{4,7,2};切割后的右子树前序序列为:{3,5,6,8},切割后的右子树中序序列为:{5,3,8,6}
    5. 对子树分别使用同样的方法分解
    6. 时间复杂度:O(n)O(n)O(n)
      空间复杂度:O(n)O(n)O(n)
import java.util.Arrays;

public class reconstructionOfBinaryTree {

    public static void main(String[] args) {
        reconstructionOfBinaryTree binaryTree = new reconstructionOfBinaryTree();
        int[] pre = {1,2,4,7,3,5,6,8};
        int[] in = {4,7,2,1,5,3,8,6};
         TreeNode root = binaryTree.reConstructBinaryTree(pre,in);
         root.preOrder();
    }
    //递归
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        if(pre.length == 0 || in.length == 0) {
            return null;
        }
        TreeNode node = new TreeNode(pre[0]);
        for(int i = 0; i < in.length; i++) {
            if(in[i] == pre[0]) {
                node.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+1), Arrays.copyOfRange(in, 0, i));
                node.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i+1, pre.length), Arrays.copyOfRange(in, i+1, in.length));
                break;
            }
        }
        return node;
    }
}
class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;
    public TreeNode(int val) {
        this.val = val;
    }
    //验证构建的二叉树  前序遍历
    public void preOrder() {
        System.out.println(this.val);
        if(this.left != null) {
            this.left.preOrder();
        }
        if(this.right != null) {
            this.right.preOrder();
        }
    }
}

5用两个栈模拟队列

  用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型

      • 当插入时,直接插入 stack1
      • 当弹出时,当 stack2 不为空,弹出 stack2 栈顶元素,如果 stack2 为空,将 stack1 中的全部数逐个出栈入栈 stack2,再弹出 stack2 栈顶元素
      • push时间复杂度:
        pop空间复杂度:O(1)
import java.util.Stack;

public class twoStacksAnalogqueue {

    public static void main(String[] args) {
        twoStacksAnalogqueue stack = new twoStacksAnalogqueue();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        System.out.println(stack.pop());
        stack.push(4);
        System.out.println(stack.pop());
        stack.push(8);
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        
    }

    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.isEmpty()) {
            while(!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        }
        return stack2.pop();
    }
}

 

import java.util.ArrayList; public class printListFromTailToHeadTest { public static void main(String[] args) { printListFromTailToHeadTest print = new printListFromTailToHeadTest(); link l = new link(); for(int i = 0;i < 10;i++) { l.add(i); } ArrayList<Integer> res = print.printListFromTailToHead(l.root); System.out.println(res.toString()); } public ArrayList<Integer> printListFromTailToHead(ListNode listNode){ ArrayList<Integer> list = new ArrayList<>(); while(listNode != null) { list.add(0,listNode.val); listNode = listNode.next; } return list; } } //链表添加结点 class link{ public ListNode root; public void add(int val) { ListNode listNode = new ListNode(val); if(this.root == null) { this.root = listNode; }else { this.root.add(listNode); } } } class ListNode{ int val; ListNode next; public ListNode(int val) { this.val = val; } public void add(ListNode listNode) { if(this.next == null) { this.next = listNode; }else { this.next.add(listNode); } } }
进口的java.util.ArrayList;

公共类printListFromTailToHeadTest {

公共静态无效的主要(字串[] args){
printListFromTailToHeadTest打印=新printListFromTailToHeadTest();
链路L =新链路();
对于(中间体I = 0;我<10; i ++在){
l.add(ⅰ);
}
的ArrayList <Integer>的解析度= print.printListFromTailToHead(l.root);
的System.out.println(res.toString());

}
公共的ArrayList <Integer>的printListFromTailToHead(ListNode listNode){
的ArrayList <Integer>的列表=新的ArrayList <>();
而(listNode!= NULL){
list.add(0,listNode.val);
listNode = listNode.next;
}
返回列表;
}

}
//链表添加结点
类链接{
公共ListNode根;
公共无效添加(INT VAL){
ListNode listNode =新ListNode(VAL);
如果(this.root == NULL){
this.root = listNode;
}其他{
this.root.add(listNode);
}
}
}
类ListNode {
INT VAL;
ListNode未来;

公共ListNode(INT VAL){
this.val = VAL;
}
公共无效添加(ListNode listNode){
如果(this.next == NULL){
this.next = listNode;
}其他{
this.next.add(listNode);
}

}
}
posted @ 2020-05-26 11:18  我们村里的小花儿  阅读(137)  评论(0编辑  收藏  举报