剑指offer打卡

news2024/12/25 23:56:17

这里写目录标题

      • day1 二叉树和为某一路径
      • day2复杂链表的复刻
      • day3二叉搜索树与双向链表
      • day4数字排列
      • day5找出出现次数超过一半的次数
      • day6 二进制中1的个数
      • day7 二叉树的最近公共祖先
      • day8 字符串转换为整数
      • day9 构建乘积数组
      • day10不用加减乘除的加法
      • day11求1+2....+n
      • day11 股票的最大价值
      • day13扑克牌的顺子
      • day14骰子的点数
      • day15滑动窗口的最大值

day1 二叉树和为某一路径

在这里插入图片描述

思路分析

  • 初步想法:这个题就是一个典型的爆搜问题,我们最简单的一个想法就是,搜索所有路径,并求和进行判断,所以我们可以使用dfs模板
  • 简化:为了判断是否于tar相等,我们需要每次递归时都传入,sum,tar两个参数,我们可以将加法转化为减法,与0进行比较
  • 在这里我们需要使用递归函数,所以采用递归三步法进行分析:定义,终止条件,单层逻辑;
class Solution {
    static List<List<Integer>> ans;
    static List<Integer> res=new ArrayList<>();
    public List<List<Integer>> findPath(TreeNode root, int sum) {
        ans=new ArrayList<>();
        dfs(root,sum);
        return ans;
    }
  
    //1.定义:对路径进行搜索,无返回值
    public static void dfs(TreeNode root,int sum){
        
        //2.递归终止条件,当传入节点为null时,则无需进行下一步递归。
        if(root==null)return;//如果为null则直接返回
        //3.单层逻辑
        res.add(root.val);//3.1将该值加入res
        sum=sum-root.val;//3.2并用sum减去该值
        //3.3判断此时的节点是否符合要求
        //**********重点**********
        /*为什么在ans.add(new ArrayList<>(res)) 要重新建立一个list?
        *答:在该题中res为成员变量,所有的方法共享一个,指向同一地址;
        *如果直接加入,在后续语句中,依旧会修改res,导致其答案不一样
        *
        */
        if(root.left==null && root.right==null && sum==0)ans.add(new ArrayList<>(res));
    
        //3.4递归处理左右子树
        dfs(root.left,sum);
        dfs(root.right,sum);
        res.remove(res.size()-1);//恢复现状,如果该条路不同则,退出该值,
        }
    

day2复杂链表的复刻

在这里插入图片描述
思路分析

  • 首先我们可以使用hash表存储每个点对应的来next指针 random指针,而后复现
  • 在这里我们还有另一种做法:
    1. 在每个点对应的后面复制每一个点
    2. 遍历链表处理random指针
    3. 将这两条互相交叉的链分开(必须将原有链恢复原样,不然会报错)
class Solution {
    public ListNode copyRandomList(ListNode head) {
        //1.在原链表的每一个节点后加上节点的复制
        if(head==null)return null;
        for(ListNode p = head ; p != null;){
            ListNode q = new ListNode(p.val);
            //防止断链
            ListNode next = p.next;
            p.next = q;
            q.next = next;
            p = next;
        }
        //2.将新加入的节点的random指针指向原链表的random指针
        for(ListNode p = head ; p != null ; p = p.next.next){
            if(p.random != null){
                //新节点的random指针指向原节点random指针指向的下一个节点
                p.next.random = p.random.next;
            }
        }
        //3.将两条链分开
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        for(ListNode p = head; p != null; p = p.next){
        cur.next = p.next;
        cur = cur.next;
        // 前面破坏了原head链表,恢复链表
        p.next = p.next.next;
}
        return dummy.next;
    }
}

day3二叉搜索树与双向链表

在这里插入图片描述
思路分析

  • 我们可以知道对于一个二叉搜索树,中序遍历与有序列表的元素顺序相同
  • 所以我们在这里使用中序遍历的模板
  • 对于中序遍历会先重最左边的节点(4)开始处理
class Solution {
    //指针:用来记录前一个节点·
    static TreeNode pre=null;
    public TreeNode convert(TreeNode root) {
        if(root==null)return null;
        dfs(root);
        while(root.left!=null)root=root.left;
        return root;
        
    }
   //我们一第一个节点4[6]来讲解这个单层逻辑 
   //1.函数定义:将二叉搜索树变为有序的双向链表,无返回值
    public static void dfs(TreeNode root){
        //2.递归终止条件:若节点为空,则结束
        if(root==null)return;
        dfs(root.left);
        //由于中序遍历,所以root 会依次是 4 6 8 10 .。。。
        root.left=pre;//   null<—4(<-6)[4<—6]
        if(pre!=null)pre.right=root;//pre为空不执行  [4—>(<——)6]
        pre=root;//pre=4;[pre=6]
        dfs(root.right);
    }
   
    
}

day4数字排列

在这里插入图片描述
思路分析

  • 很容易知道这里应该使用回溯算法求解,很经典
class Solution {
    static List<Integer> path;
    static boolean[] st;//该数是否被使用
    static Set<List<Integer>> res;
    static int n;
    public List<List<Integer>> permutation(int[] nums) {
        path=new ArrayList<>();
        st=new boolean[nums.length];
        res=new HashSet<>();
        n=nums.length;
        dfs(0,nums);
        List<List<Integer>> ans=new ArrayList<>(res);
        return ans;
        
    }
    public static void dfs(int u,int[] nums){
        if(u==n){
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i=0;i<n;i++){
            if(!st[i]){
                path.add(nums[i]);
                st[i]=true;
                dfs(u+1,nums);
            
                st[i]=false;
                path.remove(path.size()-1);
            }
            
        }
    }
}

day5找出出现次数超过一半的次数

在这里插入图片描述

class Solution {
    public int moreThanHalfNum_Solution(int[] nums) {
        int cnt=1,val=nums[0];
        for(int i=0;i<nums.length;i++){
            if(nums[i]==val)cnt++;
            else cnt--;
            //如果出现问题则进行重置
            if(cnt==0){
                val=nums[i];
                cnt=1;
            }
        }
        return val;
    }
}

测试例子解析

  • 例1:input([1,2,1,1,3])
    i=0:nums[i]=1,val=1,cnt=2
    i=1:nums[i]=2,val=1,cnt=1
    i=2:nums[i]=1,val=1,cnt=2
    i=3:nums[i]=1,val=1,cnt=3
    i=4:nums[i]=3,val=1,cnt=2

例2:input([2,0,1,1,3])
i=0:nums[i]=2,val=2,cnt=2
i=1:nums[i]=0,val=2,cnt=1
i=2:nums[i]=1,val=2,cnt=0,重置,val=1,cnt=1
i=3:nums[i]=1,val=1,cnt=2
i=4:nums[i]=3,val=1,cnt=1

day6 二进制中1的个数

在这里插入图片描述
基本知识点

  • 计算机中数的二进制表示
  • 3:00000011

  • -3:使用补码进行表示

先计算-3绝对值的二进制 00000011

取反:11111100

加1:11111101(这就是计算级的-3表示)

  • 无符号整数:计算机里的数是用二进制表示的,最左边的这一位一般用来表示这个数是正数还是负数,这样的话这个数就是有符号整数。无符号整数包括0和正数。

举例:假设有一个 数据类型有8位组成
无符号整数:8位全部表示数值;范围位[0,2^8-1]
有符号整数:最左边表示符号,后7位表示数值;范围[-111 1111,+111 1111]

  • 位运算

un&1:将二进制的个位取出
un>>>1:将个位删掉

思路分析

如果n位正数(0),我们直接挨个将每一位数字取出计算即可
负数:我们可以将负数先转换位无符号整数,在进行与正数相同操作

class Solution {
    public int NumberOf1(int n) {
        int res=0;
        int un=n & 0xffffffff;//将数字转换为无符号整数;0xffffffff表示32个1
        while(un!=0){
            res=res+(un&1);
            un=un>>>1;
        }
        return res;
        
    }
}

day7 二叉树的最近公共祖先

在这里插入图片描述这里推荐一个大佬的题解
大佬题解(非常详细有用)
思路分析

day8 字符串转换为整数

在这里插入图片描述
思路分析

按照以下步骤就可以

  • 最前面的空格
  • 判断符号
  • 数位相乘计算整数
  • char 转换位数字 :char-‘0’
class Solution {
    public int strToInt(String str) {
        long res=0;
        char[] ch=str.toCharArray();
        int k=0;//去除空格
        while(k<ch.length && ch[k]==' ')k++;
        int flag=1;
        if(k<ch.length && ch[k]=='-'){
            flag=-1;
            k++;
        }else if(k<ch.length && ch[k]=='+') k++;
        // System.out.println(k<ch.length && ch[k]>='0' && ch[k]<='9');
        while(k<ch.length && ch[k]>='0' && ch[k]<='9'){
            // System.out.println(ch[k]-'0');
            res=res*10+(ch[k]-'0');
            if (res > 1e11) break;
            k++;
        }
        // System.out.println(res);
        res=(res*flag);
        if (res > Integer.MAX_VALUE) res = Integer.MAX_VALUE;
        if (res < Integer.MIN_VALUE) res = Integer.MIN_VALUE;
        return (int)res;
    }
}

day9 构建乘积数组

在这里插入图片描述
思路分析

  • B[i]主要由 A[0,i] 与A[i+1,n-1] 两个连续部分组成

  • [0,i-1]的计算

    B[i-1]=A[0]…*A[i-2]
    B[i] =A[0]… *A[i-2] * A[i-1]
    观测可知 B[i]=B[i-1]*A[i-1]

  • 在后半部分计算有着同样的规律,所以我们可以利用两个循环来实现答案的计算

class Solution {
/*分析可知
*1.B[i]的乘积有两部分组成,[0,i-1]与[i+1,r]
*2.我们可以注意到在计算[0,i-1]部分上的B[i]乘积时,可以利用前一个B[i-1]*a[i-1]得到
*3.第二部分倒序计算时,有着相同的规律
*5.所以我们可以利用两次循环来获得结果
*/
    public int[] multiply(int[] A) {
        int[] ans=new int[A.length];
        if(A.length==0)return ans;
        ans[0]=1;
        //循环计算第一部分
        for(int i=1;i<A.length;i++){
            ans[i]=ans[i-1]*A[i-1];
        }
        //计算第二部分循环
        int tmp=1;//tmp记录前一个循环的值
        for(int i=A.length-2;i>=0;i--){
            tmp=tmp*A[i+1];
            ans[i]*=tmp;
        }
        return ans;      
    }
}

day10不用加减乘除的加法

在这里插入图片描述
思路分析

  • 这里我们利用位运算来求解
  • 位运算根据值的不同可以分为4种情况
    | a(i) | b(i) | c(i) | c(i+1) |
    | ---- | ---- | ---- | ------ |
    | 0 | 0 | 0 | 0 |
    | 0 | 1 | 1 | 0 |
    | 1 | 0 | 1| 0 |
    | 1 | 1 | 0 | 1 |
  • 本位:当两个同为1/0时,等于0;否则为1;即 本位 为 a^b
  • 进位:两个数同为 1 时 为1 所以 进位 为 a&b
  • 我们可以类比10进制,当知道10位数为a,个位数为b—> (a*10+b )
    同理,二进制即为:a&b<<1+a^b;
    由于不能用加法,我们可以多次循环值进位为0,则此时的 非进位即所求答案
    大佬详解
class Solution {
    public int add(int num1, int num2) {
        if(num2==0)return num1;
        return add(num1^num2,(num1&num2)<<1);
    }
}

day11求1+2…+n

在这里插入图片描述
思路分析

  • 根据题意不能使用循环和乘除法,所以很容易想到使用递归
  • 最小子问题 n=1 return 1;
  • 单层逻辑:n+getSum(n-1)
class Solution {
    public int getSum(int n) {
        if(n==1)return 1;
        return n+getSum(n-1);
    }
}

day11 股票的最大价值

在这里插入图片描述
思路分析

  • 状态表示
    • 状态集合:前i个元素中任选两个元素的所有选法
    • 属性:序号后-序号前的最大值
  • 状态计算
    • 不包含 nums[i] 最大值为 dp[i-1]
    • 包含nums[i] 最大值 为 nums[i]-min(前i个元素的最小值)

所以状态转移方程为 dp[i]=Math.max(dp[i-1],nums[i]-min)

day13扑克牌的顺子

day14骰子的点数

day15滑动窗口的最大值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/618139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7.1「实战」图书录入和修改API --如何优雅处理校验逻辑?

文章目录 前言一、service层BookServiceImpl.saveBook()BookBO 二、web层BookAdminControllerBookVO 最后 前言 在做了这么多架构铺垫之后&#xff0c;一位订阅同学非常期待我能更新主线API&#xff0c;我觉得他的想法非常合理&#xff0c;所以今天就来安排~~~ 我主要考虑的是…

数据库期末复习(10)数据库规范化理论

函数依赖(概念):FD 范式分解(评估准则): 模式分解(工具): 函数依赖 如何衡量一个数据库好不好:准确 高效如果一个数据库设计的不好的话的&#xff0c;会带来哪些问题 删除异常 数据冗余为什么会导致出现上方的问题:数据依赖数据依赖的分类:完全依赖&#xff0c;部分依赖&am…

OpenCV实战(26)——视频序列处理

OpenCV实战&#xff08;26&#xff09;——视频序列处理 0. 前言1. 读取视频序列2. 处理视频帧2.1 视频处理2.2 自定义视频处理类 VideoProcessor2.3 处理一系列图像2.4 使用帧处理器类 3. 存储视频序列3.1 存储视频文件3.2 修改 VideoProcessor 类3.3 编解码器四字符编码 4. 完…

第九章:子查询

第九章&#xff1a;子查询 9.1&#xff1a;子查询的基本使用 子查询的基本语法结构 SELECT .... FROM .... WHERE expr operator (SELECT ...FROM ...WHERE ...);子查询(内查询)在主查询之前一次执行完成。子查询的结果被主查询(外查询)使用。注意事项 子查询要包含在括号内。…

【JavaSE】Java(五十五):核心要点总结

文章目录 1. 为什么不允许静态方法访问非静态变量2. Java的内存模型3. 在Java中什么时候用重载什么时候用重写4. 举例说明什么情况下更倾向于用抽象类而不是接口5. 实例化对象有哪几种方式 1. 为什么不允许静态方法访问非静态变量 在Java中&#xff0c;静态方法属于类级别的方法…

【HTML】第 4 节 - 列表标签

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、缘起 2、列表 3、无序列表 4、有序列表 5、定义列表 6、总结 1、缘起 微信小程序的列表标签是一种用于展示多个数据项的…

量子 AI,是融合还是颠覆?

光子盒研究院 前言&#xff1a;如今&#xff0c;量子技术早已走出实验室、广泛赋能电力、化学、医学等各个领域&#xff1b;创新赛道上&#xff0c;加速奔跑的量子产业&#xff0c;将带来无限可能。现在&#xff0c;光子盒特开启「量子」专栏&#xff0c;一一解读量子技术将为下…

chatgpt赋能python:Python安装教程:从下载到配置

Python安装教程&#xff1a;从下载到配置 Python作为一门高级编程语言&#xff0c;越来越受到开发人员的欢迎。Python的灵活性和易用性&#xff0c;让许多人选择Python作为他们的程序语言。本文将详细介绍Python安装教程&#xff0c;帮助初学者轻松入门。 1. 下载Python安装包…

【JavaSE】Java(五十四):核心要点总结

文章目录 1. try-catch-finally中 如果 catch 中 return 了&#xff0c;finally 还会执行吗?2. 常见的异常类有哪些3. hashcode 是什么 &#xff0c;有什么作用4. java中操作字符串有哪些类&#xff0c;他们之间有什么区别5. Java 中有哪些引用类型 1. try-catch-finally中 如…

$2$驱动模块

目录 1.驱动模块&#xff08;驱动程序的框架&#xff09; 2.内核中的打印函数&#xff08;编写第一个驱动程序&#xff09; Source Insight 使用&#xff1a; 打印函数编写 分析 3.驱动的多文件编译 4.模块传递参数 安装好驱动之后如何传参&#xff1f; 多驱动之间调用&…

智能照明控制系统在现代建筑工程中的应用 安科瑞 许敏

摘要&#xff1a; 文章分析了在现代建筑工程中智能照明控制系统所具有的优越性&#xff0c;并对如何解决该技术在实际应用中遇到的问题提出了看法与建议。 关键词&#xff1a;智能照明 控制系统 应用节能 引言 随着人们的物质和精神生活水平不断提高&#xff0c;对生活的追求…

MMC整流器Matlab仿真模型子模块个数N=18(含技术文档)

资源地址&#xff1a; MMC整流器Matlab仿真模型子模块个数N&#xff1d;18&#xff08;含技术文档&#xff09;资源-CSDN文库 模型介绍&#xff1a; 1.MMC工作在整流侧&#xff0c;子模块个数N&#xff1d;18&#xff0c;直流侧电压Udc&#xff1d;25.2kV&#xff0c;交流侧…

算法设计与分析期末复习(二)

动态规划 基本思想&#xff1a;把求解的问题分成许多阶段或多个子问题&#xff0c;然后按顺序求解各个子问题。**前一个子问题的解为后一个子问题的求解提供了有用的信息。**在求解任何一子问题时&#xff0c;列出各种可能的局部解&#xff0c;通过决策保留那些有可能达到最优…

Linux面试题汇总

Linux面试题汇总 网络拓展Linux 概述什么是LinuxUnix和Linux有什么区别&#xff1f;什么是 Linux 内核&#xff1f;Linux的基本组件是什么&#xff1f;Linux 的体系结构BASH和DOS之间的基本区别是什么&#xff1f;Linux 开机启动过程&#xff1f;Linux系统缺省的运行级别&#…

javaScript蓝桥杯----外卖给好评

目录 一、介绍二、准备三、⽬标四、代码五、完成 一、介绍 外卖是现代⽣活中必备的⼀环。收到外卖后&#xff0c;各⼤平台软件常常会邀请⽤户在⼝味&#xff0c;配送速度等多个⽅⾯给与评分。在 element-ui 组件中&#xff0c;已经有相应的 Rate 组件&#xff0c;但是已有组件…

前端052_单点登录SSO_单点退出系统

单点退出系统 1、 需求分析2、EasyMock 添加退出系统模拟接口3、定义Api调用退出接口4、定义 Vuex 退出行为1、 需求分析 所有应用系统退出,全部发送请求到当前认证中心进行处理,发送请求后台删除用户登录数据,并将 cookie 中的用户数据清除。 2、EasyMock 添加退出系统模拟…

大数据分析案例-基于LightGBM算法构建银行客户流失预测模型

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

第四章:运算符

第四章&#xff1a;运算符 4.1&#xff1a;算术运算符 ​ 算术运算符主要用于数学运算&#xff0c;其可以连接运算符前后的两个数值或表达值&#xff0c;对数值或表达式进行加()、减(-)、乘(*)、除(/)、取模(%)运算。 运算符名称作用示例加法运算符计算两个值或表达式的和SE…

chatgpt赋能python:Python如何遍历文件:一篇完整的指南

Python如何遍历文件: 一篇完整的指南 在进行文件操作时&#xff0c;遍历文件是相当普遍的需求。Python中提供了多种方法来遍历文件夹和文件&#xff0c;包括os模块&#xff0c;glob模块和os.walk方法。这篇文章将会介绍这些方法及其应用。 什么是遍历文件&#xff1f; 遍历文…

使用 ConstraintLayout

ConstraintLayout解析 1.前言2.了解ConstraintLayout3.基本用法3.1 看一个布局3.2再看一个布局 1.前言 你是不是一直不敢用ConstraintLayout&#xff0c;是以为属性太多太复杂&#xff1f;你心理上的惰性&#xff0c;畏惧它。它其实很好用很强大&#xff0c;如果要用就需要一个…