剑指offer学习笔记(更新中)

本文概述了《剑指Offer》中涉及的编程问题,包括使用HashSet查找数组中重复数字、二维数组查找、字符串替换空格、链表反转、队列模拟和斐波那契数列的多种解法,展示了不同的数据结构和算法策略。
摘要由CSDN通过智能技术生成

剑指offer学习笔记

JZ3

题目描述:数组中重复的数字
解决的思路:hashset(不可以输入重复的数据);重新创建一个数组判断。
代码:

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param numbers int整型一维数组 
     * @return int整型
     */
     //hashset判断
     public int duplicate (int[] numbers) {
         // write code here
         HashSet<Integer> set = new HashSet<>();
         for (int i = 0;i<numbers.length;i++){
             if(set.add(numbers[i]))
                 return numbers[i];
         }
         return -1;
     }
    //数组判断
    public int duplicate (int[] numbers){
        int[] countarray = new int[numbers.length];
        for(int i=0;i<numbers.length;i++){
            countarray[numbers[i]]++;
            if(countarray[numbers[i]]>1){
                return numbers[i];
            }
        }
        return -1;
    }
}

JZ4

题目描述:二维数组中的查找
解决的思路:二分查找(分治)
step 1:首先获取矩阵的两个边长,判断特殊情况。
step 2:首先以左下角为起点,若是它小于目标元素,则往右移动去找大的,若是他大于目标元素,则往上移动去找小的。
step 3:若是移动到了矩阵边界也没找到,说明矩阵中不存在目标值。

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param target int整型 
     * @param array int整型二维数组 
     * @return bool布尔型
     */
    public boolean Find (int target, int[][] array) {
        // write code here
        if(array.length == 0)
            return false;
        int n = array.length;
        if(array[0].length == 0)
            return false;
        int m = array[0].length;
        for(int i = n-1,j = 0; i>=0&&j<m;){
            if(array[i][j]>target)
                i--;
            else if(array[i][j]<target)
                j++;
            else
                return true;
        }
        return false;
    }
}

JZ5 替换空格

解题思路:申请一个临时数组,然后再遍历这个字符串的每个字符,如果不是空格就把遍历的字符添加到临时数组中,如果是空格就添加3个字符’%',‘2’,'0’分别到临时数组中,最后再把临时数组转化为字符串即可。

public String replaceSpace (String s) {
        // write code here
        //先把字符串转换成字符,再转换成字符串
        int length = s.length();
        char [] array = new char[length * 3];
        int index = 0;
        for(int i=0;i < length;i++){
            char c = s.charAt(i);
            if(c == ' '){
                array[index++]='%';
                array[index++]='2';
                array[index++]='0';
            }else{
                array[index++]= c;
            }
        }
        String newstr = new String(array,0,index);
        return newstr;
    }

StringBuilder方法;好处空间O(1)

public String replaceSpace (String s) {
        StringBuilder stringbuilder = new StringBuilder();
        for(int i = 0;i<s.length();i++){
            if(s.charAt(i)==' '){
                stringbuilder.append("%20");
            }else{
                stringbuilder.append(s.charAt(i));
            }
        }
        return stringbuilder.toString();
    }

JZ6 从尾到头打印链表

解题思路:递归方法

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

非递归:
ArrayList 中有个方法是 add(index,value),可以指定 index 位置插入 value 值
所以我们在遍历 listNode 的同时将每个遇到的值插入到 list 的 0 位置,最后输出 listNode 即可得到逆序链表

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

JZ9 用两个栈实现队列

队列的特性是:“先入先出”,栈的特性是:“先入后出”

当我们向模拟的队列插入数 a,b,c 时,假设插入的是 stack1,此时的栈情况为:

栈 stack1:{a,b,c}
栈 stack2:{}
当需要弹出一个数,根据队列的"先进先出"原则,a 先进入,则 a 应该先弹出。但是此时 a 在 stack1 的最下面,将 stack1 中全部元素逐个弹出压入 stack2,现在可以正确的从 stack2 中弹出 a,此时的栈情况为:

栈 stack1:{}
栈 stack2:{c,b}
继续弹出一个数,b 比 c 先进入"队列",b 弹出,注意此时 b 在 stack2 的栈顶,可直接弹出,此时的栈情况为:

栈 stack1:{}
栈 stack2:{c}
此时向模拟队列插入一个数 d,还是插入 stack1,此时的栈情况为:

栈 stack1:{d}
栈 stack2:{c}
弹出一个数,c 比 d 先进入,c 弹出,注意此时 c 在 stack2 的栈顶,可直接弹出,此时的栈情况为:

栈 stack1:{d}
栈 stack2:{c}
根据上述栗子可得出结论:

当插入时,直接插入 stack1
当弹出时,当 stack2 不为空,弹出 stack2 栈顶元素,如果 stack2 为空,将 stack1 中的全部数逐个出栈入栈 stack2,再弹出 stack2 栈顶元素

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

JZ10 斐波那契数列

思路:递归法

		if(n<=2){
            return 1;
        }
        return Fibonacci(n-1)+Fibonacci(n-2);

动态规划五步,1先确定dp[ ],dp[i],2确定递推公式,dp[i]=dp[i-1]+dp[i-2],3初始化dp数组,dp[0]=0,dp[1]=1;,4确定遍历顺序,5举例推到dp数组

		if(n<=1){
            return n;
        }
        int dp[] = new int[n+1];
        dp[0]=0;
        dp[1]=1;
        for(int i =2;i<=n;i++){
            dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[n];
        

优化上面算法,观察可以发现我们不用每次都记录整个dp数组,只需要记录两个数字就行

		if(n<=1){
            return n;
        }
        int dp[] = new int[n+1];
        dp[0]=0;
        dp[1]=1;
        for(int i =2;i<=n;i++){
            int sum = dp[0]+dp[1];
            dp[0]=dp[1];
            dp[1]=sum;
        }
        return dp[1];
  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值