刷题笔记【7】| 快速刷完67道剑指offer(Java版)

news2024/11/19 8:36:49

在这里插入图片描述

本文已收录于专栏
🌻
《刷题笔记》

文章目录

  • 前言
  • 🎨 1、二叉树中和为某一值的路径
    • 题目描述
    • 思路(深度优先搜索)
  • 🎨 2、复杂链表的复制
    • 题目描述
    • 思路
  • 🎨 3、二叉搜索树与双向链表
    • 题目描述
    • 思路
  • 🎨 4、字符串的排列
    • 题目描述
    • 思路(递归+回溯)

前言

题目来源参考阿秀学长的刷题笔记,小戴只是把 C++的题解改成了 Java版本,并整理了其他思路,便于自己的学习~

如果解题有更好的方法,本文也会及时进行更新~

希望对你有帮助~ 一起加油哇~

🎨 1、二叉树中和为某一值的路径

牛客原题链接

题目描述

输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径

思路(深度优先搜索)

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 {
    private ArrayList<ArrayList<Integer>> res;
    private ArrayList<Integer> path;

    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int expectNumber) {
        res = new ArrayList<>();
        path = new ArrayList<>();
        dfs(root,expectNumber);
        return res;
    }

    public void dfs(TreeNode root,int expectNumber){
        // 处理树为空
        if(root == null) return;

        path.add(root.val);
        expectNumber -= root.val;
        if(root.left == null && root.right == null && expectNumber == 0){
            res.add(new ArrayList<>(path));
        }

        // 左右子树递归
        dfs(root.left,expectNumber);
        dfs(root.right,expectNumber);
        // 回溯
        path.remove(path.size()-1);
    }
}

🎨 2、复杂链表的复制

牛客原题链接

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路

/*
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 cur = pHead;
        // 遍历原始链表,复制链表节点
        while(cur != null){
            // 拷贝节点
            RandomListNode clone = new RandomListNode(cur.label);
            // 将新节点插入到被拷贝的节点之后
            clone.next = cur.next;
            cur.next = clone;
            cur = clone.next;
        }
        // 遍历原始链表,复制随机节点
        cur = pHead;
        RandomListNode clone = pHead.next;
        while(cur != null){
            if(cur.random == null){
                clone.random = null;
            }else{
                clone.random = cur.random.next;
            }
            cur = cur.next.next;
            if(clone.next != null){
                clone = clone.next.next;
            }
        }
        RandomListNode res = pHead.next;
        // 遍历链表,进行拆分
        cur = pHead;
        clone = pHead.next;
        while(cur != null){
            cur.next = cur.next.next;
            cur = cur.next;
            if(clone.next != null){
                clone.next = clone.next.next;
            }
            clone = clone.next;
        }

        return res;
    }
}

🎨 3、二叉搜索树与双向链表

牛客原题链接

题目描述

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

思路

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

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

    }

}
*/
public class Solution {
    // 返回的第一个指针,即为最小值,先定为null
    public TreeNode head = null;
    // 中序遍历当前值的上一位,初值为最小值,先定为null
    public TreeNode pre = null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree == null){
            return null;
        }
        // 首先递归到最左最小值
        Convert(pRootOfTree.left);
        // 找到最小值,初始化head和pre
        if(pre == null){
            head = pRootOfTree;
            pre = pRootOfTree;
        }
        // 当前节点与上一节点建立连接,将pre设置为当前值
        else{
            pre.right = pRootOfTree;
            pRootOfTree.left = pre;
            pre = pRootOfTree;
        }
        Convert(pRootOfTree.right);
        return head;
    }
}

🎨 4、字符串的排列

牛客原题链接

题目描述

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

思路(递归+回溯)

  • 先对字符串按照字典序排序,获取第一个排列情况。
  • 准备一个空串暂存递归过程中组装的排列情况。使用额外的vis数组用于记录哪些位置的字符被加入了。
  • 每次递归从头遍历字符串,获取字符加入:首先根据vis数组,已经加入的元素不能再次加入了;同时,如果当前的元素str[i]与同一层的前一个元素str[i-1]相同且str[i-1]已经用,也不需要将其纳入。
  • 进入下一层递归前将vis数组当前位置标记为使用过。
  • 回溯的时候需要修改vis数组当前位置标记,同时去掉刚刚加入字符串的元素,
  • 临时字符串长度到达原串长度就是一种排列情况。
import java.util.*;
public class Solution {
    public void recursion(ArrayList<String> res,char[] str,StringBuffer temp,boolean[] vis){
        if(temp.length() == str.length){
            res.add(new String(temp));
            return;
        }
        // 遍历所有元素选取一个加入
        for(int i = 0; i < str.length; i++){
            // 如果该元素已经被加入,则不需要再加入了
            if(vis[i]){
                continue;
            }
            if(i > 0 && str[i-1] == str[i] && !vis[i-1]){
                // 当前元素str[i]与同一层的前一个元素str[i-1]相同且str[i-1]已经被使用
                continue;
            }
            // 标记为使用过
            vis[i] = true;
            // 加入临时字符串
            temp.append(str[i]);
            recursion(res,str,temp,vis);
            //回溯
            vis[i] = false;
            temp.deleteCharAt(temp.length()-1);
        }
    }
    public ArrayList<String> Permutation(String str) {
        ArrayList<String> res = new ArrayList<String>();
        if(str == null || str.length() == 0){
            return res;
        }
        // 转字符数组
        char[] charStr = str.toCharArray();
        // 按字典序排序
        Arrays.sort(charStr);
        boolean[] vis = new boolean[str.length()];
        // 标记每个位置的字符是否被使用过
        Arrays.fill(vis,false);
        StringBuffer temp = new StringBuffer();
        // 递归获取
        recursion(res,charStr,temp,vis);
        return res;
    }
}

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

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

相关文章

【蓝桥杯省赛真题20】python二次加密 青少年组蓝桥杯比赛python编程省赛真题解析

目录 python二次加密 一、题目要求 1、编程实现 2、输入输出 二、解题思路

STATS 782 - Numerical Computation

文章目录 一、Simple Graphics1. 用 plot&#xff08;&#xff09;函数画图 二、Optimization1. 简单求最值2. Interpolation&#xff08;插值&#xff09;3. optim&#xff08;&#xff09;函数 一、Simple Graphics 1. 用 plot&#xff08;&#xff09;函数画图 x 和 y&…

Linux常用命令——iptables命令

在线Linux命令查询工具 iptables Linux上常用的防火墙软件 补充说明 iptables命令是Linux上常用的防火墙软件&#xff0c;是netfilter项目的一部分。可以直接配置&#xff0c;也可以通过许多前端和图形界面配置。 补充说明 - 语法选项基本参数 - 命令选项输入顺序工作机制…

【java】CGLIB动态代理原理

文章目录 1. 简介2. 示例3. 原理4. JDK动态代理与CGLIB动态代理区别&#xff08;面试常问&#xff09; 1. 简介 CGLIB的全称是&#xff1a;Code Generation Library。 CGLIB是一个强大的、高性能、高质量的代码生成类库&#xff0c;它可以在运行期扩展Java类与实现Java接口&a…

【SAP Abap】X-DOC:SE43 - SAP 用户菜单定义

X-DOC&#xff1a;SE43 - SAP 用户菜单定义 1、菜单结构2、菜单配置3、菜单自定义4、实践演示 1、菜单结构 SAP的菜单栏&#xff0c;支持按层次结构配置&#xff0c;包括以下两个概念&#xff1a; &#xff08;1&#xff09;菜单项&#xff1a;具体的一个菜单目录或菜单项&…

爬虫日常-12306自动购票程序

文章目录 前言页面分析代码设计 前言 hello兄弟们&#xff0c;最近在钻研新鲜知识&#xff0c;一不留神没想起来更新。今天我们顺着前面几篇文章完整的写出一篇12306的自动购票软件。 首先把我们已经写完的前期步骤代码再顺一遍 from selenium.webdriver import Chrome from…

阿里大佬都在熬夜肝的Java程序优化笔记,程序性能提高了5倍!

前言 此笔记从软件设计、编码和JVM等维度阐述性能优化的方法和技巧&#xff0c;分享资深架构师Java程序性能优化的宝贵经验&#xff0c;专注于Java应用程序的优化方法、技巧和思想&#xff0c;并深度剖析JDK部分的实现。具有较强的层次性和连贯性&#xff0c;深入剖析软件设计…

Word控件Spire.Doc 【脚注】教程(5):单词脚注的位置与数字格式

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

1.19 从0开始学习Unity游戏开发--扩展编辑器

在之前的篇章里面&#xff0c;我们一直在编辑器里面干活&#xff0c;然后做好资源的编辑和代码开发后&#xff0c;我们可以直接在编辑器内点击那个播放按钮就能真实的把游戏跑起来&#xff0c;但是有时候&#xff0c;我们可能希望在菜单里面加个按钮&#xff0c;这样我们可以直…

C++ STL学习之【容器适配器】

✨个人主页&#xff1a; 夜 默 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 A year from now you may wish you had started today. 明年今日&#xff0c;你会希望此时此刻的自己已经开始行动了。 文章目录 &#x1f307;前言&a…

内存泄漏动态检测(valgrind)

初步判断是否有泄漏 Linux 内存性能优化 —— 高内存使用及内存泄漏排查 比如该文的介绍&#xff0c;需要初步了解top free -h等命令&#xff1b; 主要看free 内存泄漏检测方法&#xff1a; 静态我常用的是cppcheck&#xff1b; 动态的 Linux下内存泄漏定位方法 这个文章…

Node.js 一:基础

1.node.js是什么&#xff1a; 2.node.js的作用&#xff1a; 1.服务器应用&#xff1a;b站.. 2.开发工具类应用&#xff1a;webpack&#xff0c;bable等等 3.桌面端应用&#xff1a;vscode&#xff0c;postman等 这些应用都是基于electron框架开发&#xff0c;electron基于node…

【设计模式】23种设计模式之行为型模式

一、模板方法模式 1、豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下: 1&#xff09;、制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎 2&#xff09;、通过添加不同的配料&#xff0c;可以制作出不同口味的豆浆 3&#xff09;、选材、浸泡和放…

拥抱还是革命,ChatGPT时代 AI专家给出15条科研生存之道

来源&#xff1a;专知 微信号&#xff1a;Quan_Zhuanzhi 你是学术机构的人工智能研究员吗?你是否担心自己无法应对当前人工智能的发展步伐?您是否觉得您没有(或非常有限)访问人工智能研究突破所需的计算和人力资源?你并不孤单; 我们有同样的感觉。越来越多的人工智能学者不…

vuepress-yarn-nodes-静态网页_个人博客搭建

nodes官网&#xff1a;https://nodejs.org/en 先下载nodes进行安装&#xff0c;一般nodes会自带包管理器npm&#xff0c;注意npm与nodes的对应关系&#xff0c;除了npm之外还有yarn包管理器&#xff0c;一般会用npm安装这个包 npm install --global yarnnpm降低版本的方法 np…

LeetCode 1026. 节点与其祖先之间的最大差值

【LetMeFly】1026.节点与其祖先之间的最大差值 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-difference-between-node-and-ancestor/ 给定二叉树的根节点 root&#xff0c;找出存在于 不同 节点 A 和 B 之间的最大值 V&#xff0c;其中 V |A.val - B.val…

《花雕学AI》24:如何用万能Prompt公式与ChatGPT进行高效的对话测试

引言 你是否想要与人工智能进行有趣、有价值、有说服力的对话&#xff1f;你是否想要使用ChatGPT这个强大而灵活的对话生成器来创造出任何类型和主题的对话&#xff1f;如果是这样&#xff0c;那么你需要了解一个简单而强大的工具&#xff0c;就是万能Prompt公式。 万能Promp…

微软office认证课程

感谢阅读 非原创声明&#xff0c;根据微软课程学习理解而已Get started with Microsoft 365Work Smarter with Microsoft Word与 Microsoft Word 更加智能地工作Microsoft 365 SubscriptionsMicrosoft 365 订阅个人补充Exercise: Finding Help and changing account settings练…

cpp 程序与 c 程序的相互调用(extern “C“ 的使用)

实际在编译的过程中&#xff0c;.cpp 文件调用 .c文件中的函数会出错。假设代码结构如下&#xff1a; 目录 一、编译过程分析 1、预处理 2、编译 3、汇编 4、链接 二、问题解决 1、解决方案 2、解决思路 一、编译过程分析 1、预处理 该阶段头文件会被展开&#xff0c…

FPGA学习笔记(二):时序逻辑之计数器

与组合逻辑&#xff08;给定输入&#xff0c;输出是确定的&#xff0c;与时间无关&#xff09;相比较&#xff0c;时序逻辑不仅仅与输入信号相关&#xff0c;还与时钟信号相关。 D触发器&#xff1a;在上升沿时&#xff08;CLK&#xff09;才将输出&#xff08;Q&#xff09;修…