day10 11 12-牛客67道剑指offer-JZ83、18、84、69、44、11、56、85、84、89、68

news2024/11/20 1:29:38

文章目录

  • 1. JZ83 剪绳子(进阶版)
  • 2. JZ18 删除链表的节点
  • 3. JZ69 跳台阶
  • 4. JZ44 数字序列中某一位的数字
  • 5. JZ11 旋转数组的最小数字
  • 6. JZ56 数组中只出现一次的两个数字
    • 统计频率
    • 位运算
  • 7. JZ85 连续子数组的最大和(二)
  • 8. JZ84 二叉树中和为某一值的路径(三)
    • 两次dfs
    • 一次dfs+哈希表
  • 9. JZ86 在二叉树中找到两个节点的最近公共祖先
  • 10. JZ68 二叉搜索树的最近公共祖先

1. JZ83 剪绳子(进阶版)

只能分成2和3,暴力乘法会超时

class Solution {
public:
    long long cutRope(long long number) {
        if(number < 2) return 0;
        if(number < 4) return number-1;
        //暴力乘方 超时
        long long result = 1, mod = 998244353;
        //只能分成 2 3  要对998244353 取模
        while(number > 4)
        {
            result *= 3;
            result %= mod;
            number -= 3;
        }
        result *= number;
        result %= mod; 
        return result;
    }
};

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3个数越多答案越大,所以n%3有三种情况:

  • 余数为0直接做3^(n/3)
  • 余数为1做4*3^((n-4)/3)
  • 余数为2做2*3^((n-2)/3)

2. JZ18 删除链表的节点

在这里插入图片描述

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        if(head == nullptr) return nullptr;
        //写法1
        ListNode* fast = head;//找到删除节点
        ListNode* dummyhead = new ListNode(0);
        ListNode* slow = dummyhead;//断开连接
        dummyhead->next = head;

        while(fast)
        {
            if(fast->val == val)
            {
                slow->next = fast->next;
                break;
            }
            fast = fast->next;
            slow = slow->next;
        }
        return dummyhead->next;
    }
};
  • 写法2
/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        if(head == nullptr) return nullptr;

        //写法2
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode* fast = dummyhead;
        while(fast->next)
        {
            if(fast->next->val == val)
            {
                fast->next = fast->next->next;
                break;
            }
            fast = fast->next;
        }
        return dummyhead->next;
    }
};

3. JZ69 跳台阶

在这里插入图片描述

class Solution {
public:
    int jumpFloor(int number) {
        if(number <= 2) return number;

        int fistjump = 1;
        int secondjump = 2;
        int res = 0;
        for(int i=3; i<=number; i++)
        {
            res = fistjump + secondjump;
            fistjump = secondjump;
            secondjump = res;
        }
        return res;
    }
};

4. JZ44 数字序列中某一位的数字

在这里插入图片描述

#include <string>
class Solution {
public:
    int findNthDigit(int n) {
        if(n <= 9) return n;
        /*
        小于10的数字一位数,1~9,共9个数字,9位                1位数 区间是 1~9      起点是1      9个数字     9位;
        小于100的数字两位数,10~99,共90个数字,180位          2位数 区间是 10~99    起点是10     90个数字    180位;
        小于1000的数字三位数,100~999,共900个数字,2700位     3位数 区间是 100~999  起点是100    900个数字   2700位;
        
        */
        int digit = 1;           //  n是几位数
        long long start = 1;    //  当前位数 所在的区间
        long long total = 9;     //  当前区间 之前总共有多少位数字
        while(n > total) //不是1位数
        {
            n -= total;
            digit++;
            start *= 10;
            total = 9 * digit * start;//每个数字digit位 
        }
        int num = start + (n-1) / digit;//定位n在哪个区间
        int index = (n-1) % digit;//定位n在该区间的哪一位 也就是往后偏移
        return to_string(num)[index] - '0';
    }
};

5. JZ11 旋转数组的最小数字

在这里插入图片描述

#include <climits>
class Solution {
public:
    int minNumberInRotateArray(vector<int>& nums) {
        if(nums.size() <= 0) return 0;
        int left=0, right=nums.size()-1;
        while(left <= right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] > nums[right])//右边是降序 最小的数字在mid右边
                left = mid+1;
            else if(nums[mid] < nums[right])//右边是升序 最小数字要么是mid(奇数个数字) 要么在mid左边(偶数个)
                right = mid;
            else right--;//无法判断,一个一个试
            
        }
        return nums[left];
    }
};

6. JZ56 数组中只出现一次的两个数字

在这里插入图片描述

统计频率

#include <algorithm>
class Solution {
public:
    vector<int> FindNumsAppearOnce(vector<int>& nums) {
        int len = nums.size(), index=0;
        vector<int> result;
        unordered_map<int, int> hashmap;
        for(auto n : nums)
        {
            hashmap[n]++;
        }
        auto beg = nums.begin();
        auto end = nums.end();
        while(beg != nums.end())
        {
            if(hashmap[*beg] == 1)
            {
                result.push_back(*beg);
                break;
            }
            beg++;
        }
        while(end != nums.begin())
        {
            if(hashmap[*end] == 1)
            {
                result.push_back(*end);
                break;
            }
            end--;
        }
        if(result[0] > result[1]) swap(result[0], result[1]);
        return result;
    }
};

位运算

#include <algorithm>
class Solution {
public:
    vector<int> FindNumsAppearOnce(vector<int>& nums) {
        int len = nums.size(), index=0;
        vector<int> result(2, 0);
        //位运算
        // 先将全部数进行异或运算,得出得到a^b
        int tmp  = 0;
        for(int n : nums)
            tmp ^= n;
        //找到两个数不相同的第一位 从最低位开始找起
        int mask = 1;
        while((mask & tmp) == 0)
            mask <<= 1;
        //遍历数组,对每个数分类
        for(int i=0; i<nums.size(); i++)
        {
            if((mask & nums[i]) == 0) result[0] ^= nums[i];
            else result[1] ^= nums[i];
        }
        //整理次序
        if(result[0] > result[1]) swap(result[0], result[1]);
        return result;
    }
};

7. JZ85 连续子数组的最大和(二)

在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    vector<int> FindGreatestSumOfSubArray(vector<int>& array) {
        vector<int> result;
        //滑动区间
        int left = 0, right = 0;
        //记录最长的区间
        int resl = 0, resr = 0;

        int last_sum = array[0], now_sum = 0, maxsum = last_sum;

        for(int i=1; i<array.size(); i++)
        {
            right++;
            //状态转移:连续子数组和最大值
            now_sum = max(array[i], last_sum + array[i]);
            //区间新起点
            if(last_sum + array[i] < array[i])
                left = right;
            //更新最大值
            if(now_sum > maxsum || now_sum == maxsum && (right - left + 1) > (resr - resl + 1))
            {
                maxsum = now_sum;
                resl = left;
                resr = right;
            }
            //更新x的状态
            last_sum = now_sum;
        }
        //取数组
        for(int i = resl; i <= resr; i++)
            result.push_back(array[i]);
        return result;
    }
};

dp写法

class Solution {
public:
    vector<int> FindGreatestSumOfSubArray(vector<int>& array) {
        vector<int> result;
        //滑动区间
        int left = 0, right = 0;
        //记录最长的区间
        int resl = 0, resr = 0;
        //dp 写法2
        vector<int> dp(array.size(), 0);
        dp[0] = array[0];
        int maxnum = dp[0];
        for(int i=1; i<array.size(); i++)
        {
            right++;
            //状态转移:连续子数组和最大值
            dp[i] = max(dp[i-1] + array[i], array[i]);
            //区间新起点
            if(dp[i-1] + array[i] < array[i])
                left = right;
            //更新最大值
            if(dp[i] > maxnum || dp[i] == maxnum && (right - left + 1) > (resr - resl + 1))
            {
                maxnum = dp[i];
                resl = left;
                resr = right;
            }
        }
        //取数组
        for(int i = resl; i <= resr; i++)
            result.push_back(array[i]);
        return result;
    }
};

8. JZ84 二叉树中和为某一值的路径(三)

在这里插入图片描述
这个题特殊在每一个结点都可能是起始结点。

两次dfs

在这里插入图片描述

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    int count=0;
    int FindPath(TreeNode* root, int sum) {
        if(root==nullptr) return count;
        dfs(root, sum);             //查询以某节点为根的路径数
        FindPath(root->left, sum);  //以其子节点为新根
        FindPath(root->right, sum); //以其子节点为新根
        return count;
    }
    //根节点作为起始节点 
    void dfs(TreeNode* root, int sum)
    {
        if(root == nullptr) return;
        if(sum == root->val)            //符合目标值
            count++;
        //进入子节点继续找
        dfs(root->left, sum - root->val);
        dfs(root->right, sum - root->val);
    }
};

一次dfs+哈希表

在这里插入图片描述
哈希表存的是根节点到某一结点的 路径和 与 路径数,然后从该结点开始遍历其子树,累加遍历的结点值temp(相当于路径的后半段),如果temp-sum在哈希表里出现过,就说明这条路径符合要求。不是很会

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
#include <unordered_map>
class Solution {
public:
    //记录路径和 及 路径条数
    unordered_map<int, int> hashmap;
    int FindPath(TreeNode* root, int sum) {
        //一次dfs+哈希
        //路径和为0的有1条
        hashmap[0] = 1;
        return dfs2(root, sum, 0);
    }
    
    //一次dfs+哈希
    int dfs2(TreeNode* root, int sum, int lastsum)
    {
        //
        if(root == nullptr) return 0;
        int result =0;
        //到目前结点为止的累加和
        int temp = root->val + lastsum;                 
        //如果该累加和减去sum在哈希表中出现过,相当于减去前面的分支
        if(hashmap.find(temp - sum) != hashmap.end())
            //加上有的路径数
            result += hashmap[temp - sum];
        //增加该次路径和
        hashmap[temp]++;
        //进入子结点
        result += dfs2(root->left, sum, temp);
        result += dfs2(root->right, sum, temp);
        //回退该路径和,因为别的树枝不需要这边存的路径和
        hashmap[temp]--;
        return result;
    }
};

9. JZ86 在二叉树中找到两个节点的最近公共祖先

在这里插入图片描述
两种情况,一是左子树出现结点p(q),右子树出现节点q(p),那么该节点就是节点p和q的最近公共祖先,如7、4最近公共祖先是2;二是节点本身p(q),它拥有一个子孙节点q§,如5、6最近公共祖先是5。
在这里插入图片描述

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    int lowestCommonAncestor(TreeNode* root, int o1, int o2) {
        return dfs(root, o1, o2)->val;
    }
    TreeNode* dfs(TreeNode* root, int o1, int o2)
    {
        if(root == nullptr || root->val == o1 || root->val == o2)
            return root;
        TreeNode* left = dfs(root->left, o1, o2);
        TreeNode* right = dfs(root->right, o1, o2);
        if(left == nullptr) return right;
        if(right == nullptr) return left;
        return root;
    }
};

10. JZ68 二叉搜索树的最近公共祖先

在这里插入图片描述

  1. 因为是有序树,所有 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。即 中节点 > p && 中节点 < q 或者 中节点 > q && 中节点 < p。
  2. 和二叉树的公共祖先不一样的是,从上往下找,因为要找最近的公共祖先,如图
    在这里插入图片描述
    此时节点5是不是最近公共祖先? 如果 从节点5继续向左遍历,那么将错过成为q的祖先, 如果从节点5继续向右遍历则错过成为p的祖先。
    所以当我们从上向下去递归遍历,第一次遇到 root 节点是数值在[p, q]区间中,那么root 就是 p和q的最近公共祖先。
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    int lowestCommonAncestor(TreeNode* root, int p, int q) {
        //空树找不到公共祖先
        if(root == nullptr) return -1;
        //pq在该节点两边说明这就是最近公共祖先
        if((p >= root->val && q <= root->val) || (p <= root->val && q >= root->val))
            return root->val;
        // 最近公共祖先在左子树
        else if(root->val > p && root->val > q)
            return lowestCommonAncestor(root->left, p, q);
        // 最近公共祖先在右子树
        else
            return lowestCommonAncestor(root->right, p, q);
    }
};

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

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

相关文章

set_output_delay的本质

set_output_delay是对模块output信号在模块外部延迟的约束&#xff0c;本质上EDA工具会根据约束调整内部器件&#xff08;UFF0&#xff09;的类型&#xff0c;摆放位置以及组合逻辑&#xff08;C1&#xff09;以满足约束要求&#xff0c;即EDA工具保证模块DUA的UFF0的Tclk2qTc1…

复数

文章目录 复数虚数 i i i几何解释 复数复数的性质复数的加法1. 加实部2. 加虚部3. 组合实部和虚部复数加法的几何解释总结 复数减法1. 减实部2. 减虚部3. 组合实部和虚部复数减法的几何解释总结 复数乘法1. 展开乘法2. 使用 i 2 − 1 i^2 -1 i2−13. 合并实部和虚部复数乘法…

100 道 Python 经典面试题超强汇总(三):Python 对象内部

《Python Cookbook》的作者David Beazley的课程PPT开源了&#xff0c;目标用户是希望从编写基础脚本过渡到编写更复杂程序的高级 Python 程序员&#xff0c;课程主题侧重于流行库和框架中使用的编程技术&#xff0c;主要目的是更好地理解 Python 语言本身&#xff0c;以便阅读他…

(JavaScript笔记摘要)一次性搞定原型和原型链

一、前言 学完JavaScript ES5基础语法&#xff08;核心语法&#xff09;后&#xff0c;发现根本不够用&#xff0c;于是选择继续精进JavaScript功底 学到原型和原型链时&#xff0c;发现有点卡壳儿&#xff0c;于是投入了一定精力&#xff0c;进行了汇总整理和吸收&#xff0c…

知识体系总结(九)设计原则、设计模式、分布式、高性能、高可用

文章目录 架构设计为什么要进行技术框架的设计 六大设计原则一、单一职责原则二、开闭原则三、依赖倒置原则四、接口分离原则五、迪米特法则&#xff08;又称最小知道原则&#xff09;六、里氏替换原则案例诠释 常见设计模式构造型单例模式工厂模式简单工厂工厂方法 生成器模式…

【Kubernetes】Kubernetes之配置资源管理

Secret 和 ConfigMap 一、Secret1. Secret 的作用2. Secret 的类型3. Secret 使用方式及应用场景4. Secret 的实例4.1 创建 Secret4.2 使用方式将 Secret 挂载到 Volume 中&#xff0c;以 Volume 的形式挂载到 Pod 的某个目录下将 Secret 导出到环境变量中 二、 ConfigMap1. Co…

由于找不到mfc140u.dll,无法继续执行代码怎么修复?

当我在使用某个应用程序时遇到了mfc140u.dll缺失的错误提示时&#xff0c;我意识到这是由于该动态链接库文件丢失或损坏所引起的。mfc140u.dll是MFC的一部分&#xff0c;它包含了许多与用户界面、窗口管理、控件等相关的函数和类。这个文件通常用于支持使用MFC开发的应用程序的…

高效服务器DDoS防护,F5安全架构不可少

数字化转型&#xff0c;特别是现代化应用正面临着严峻挑战。如何确保应用的用户体验&#xff0c;用户现有安全架构如何适应现代化应用防护需求&#xff0c;以及 API 安全直接关乎现代化应用的普及和用户的体验&#xff0c;甚至关系到企业数字化能否转型成功。当企业网站或服务器…

HD Supply EDI 项目测试流程

在此前的文章 HD Supply EDI 项目案例中&#xff0c;我们已经为大家介绍了 HD Supply EDI 项目案例&#xff0c;了解了 HD Supply 业务测试场景&#xff0c;本文将为大家介绍 EDI 项目测试流程。 HD Supply EDI 项目连接测试 在HD Supply EDI 项目中&#xff0c;CommerceHub为…

[oneAPI] 手写数字识别-BiLSTM

[oneAPI] 手写数字识别-BiLSTM 手写数字识别参数与包加载数据模型训练过程结果 oneAPI 比赛&#xff1a;https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517 Intel DevCloud for oneAPI&#xff1a;https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToo…

[obs] 编译记录

2023.7 obs 最近编译方式经常改。本次使用的是最新的方式编译 2023/7月份版本&#xff0c;记录一下遇到的坑 obs 最新版默认使用 vs2022 才能编译&#xff0c;如果想用 vs2019 编译&#xff0c;改下面这个地方就好了 CMakePresets.json 文件的obs aja 编译有问题 解决方案&a…

【方法】如何给分卷压缩文件添加密码?

在压缩文件的时候&#xff0c;如果文件比较大&#xff0c;或者网盘单个文件限制了大小&#xff0c;很多人会选择将文件压缩成分卷文件。 如果文件还有保密需求&#xff0c;那如何在压缩文件时设置分卷&#xff0c;又同时设置密码保护呢&#xff1f;下面小编来举例看看如何操作…

测试平台开发:(19)自动化测试脚本工具化 2

上一篇:测试平台开发:(18)自动化测试脚本工具化_要开朗的spookypop的博客-CSDN博客 本篇先实现创建自动化脚本的功能,将selenium代码语言转化为文字语言,如下图所示: 例1:比如下面的代码,转化为语言“用谷歌浏览器打开XX页面”: service = ChromeService(executabl…

【Python】基础语法:变量类型和动态类型

文章目录 1. 常量2. 变量3. 动态类型特性 努力经营当下 直至未来明朗 1. 常量 浮点数在内存中表示使用的是IEEE754标准&#xff0c;这套规则下&#xff0c;在内存中表示该浮点数额时候可能会存在微小的误差 在进行运算的时候&#xff0c;最好可以将数字&#xff08;字面值常…

如何理解“I/O指令是CPU系统指令的一部分”?

I/O指令作用过程&#xff08;以 I/O端口独立编址方式为例&#xff09;&#xff1a; CPU识别出当前指令是I/O指令&#xff0c;向I/O总线发送相应控制信号和地址信息。 之前迷惑的点&#xff1a;默认以为I/O指令是作用于I/O接口的&#xff0c;进而产生疑问&#xff0c;I/O接口中…

期权行权和不行权的区别

对于期权小白刚入门来说&#xff0c;期权是一种金融衍生品&#xff0c;简单理解期权就是大盘指数为标的物&#xff0c;可以做多和做空&#xff0c;在期权到期日最后一天&#xff0c;你面临持仓合约是选择行权呢还是不行权&#xff0c;下文科普期权行权和不行权的区别&#xff0…

03.Spring Security 如何保护用户密码

1. 前言 上一文我们对Spring Security中的重要用户信息主体UserDetails进行了探讨。中间例子我们使用了明文密码&#xff0c;规则是通过对密码明文添加{noop}前缀。那么本节将对 Spring Security 中的密码编码进行一些探讨。 2. 不推荐使用md5 首先md5 不是加密算法&#xf…

前端跨域的原因以及解决方案(vue),一文让你真正理解跨域

跨域这个问题,可以说是前端的必需了解的,但是多少人是知其然不知所以然呢&#xff1f; 下面我们来梳理一下vue解决跨域的思路。 什么情况会跨域&#xff1f; ​ 跨域的本质就是浏览器基于同源策略的一种安全手段。所谓同源就是必须有以下三个相同点&#xff1a;协议相同、域名…

网络套接字

网络套接字 文章目录 网络套接字认识端口号初识TCP协议初识UDP协议网络字节序 socket编程接口socket创建socket文件描述符bind绑定端口号sockaddr结构体netstat -nuap&#xff1a;查看服务器网络信息 代码编译运行展示 实现简单UDP服务器开发 认识端口号 端口号(port)是传输层协…

Python 3 使用HBase 总结

HBase 简介和安装 请参考文章&#xff1a;HBase 一文读懂 Python3 HBase API HBase 前期准备 1 安装happybase库操作hbase 安装该库 pip install happybase2 确保 Hadoop 和 Zookeeper 可用并开启 确保Hadoop 正常运行 确保Zookeeper 正常运行3 开启HBase thrift服务 使用命…