CSDN每日一题学习训练——Java版(字符串相乘、子集、删除链表的倒数第 N 个结点)

版本说明

当前版本号[20231112]。

版本修改说明
20231112初版

目录

文章目录

  • 版本说明
  • 目录
  • 字符串相乘
    • 题目
    • 解题思路
    • 代码思路
    • 补充说明
    • 参考代码
  • 子集
    • 题目
    • 解题思路
    • 代码思路
    • 参考代码
  • 删除链表的倒数第 N 个结点
    • 题目
    • 解题思路
    • 代码思路
    • 参考代码

字符串相乘

题目

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

示例 1:

输入: num1 = “2”, num2 = “3”
输出: “6”

示例 2:

输入: num1 = “123”, num2 = “456”
输出: “56088”

说明:

num1 和 num2 的长度小于110。
num1 和 num2 只包含数字 0-9。
num1 和 num2 均不以零开头,除非是数字 0 本身。
不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。

解题思路

  1. 首先判断输入的两个字符串是否为0,如果是则直接返回"0"。
  2. 获取两个字符串的长度m和n。
  3. 创建一个长度为m+n-1的整数数组intRes,用于存储乘积的结果。
  4. 使用两层循环遍历num1和num2的每一位数字,将它们相乘并累加到intRes数组中对应的位置。
  5. 从intRes数组的末尾开始向前遍历,如果当前位置的值大于等于10,则需要进位。将当前位置的值除以10,并将余数加到前一位上。
  6. 将intRes数组转换为字符串形式,即为最终的乘积结果。

代码思路

  1. 首先判断输入的两个字符串是否为"0",如果是,则直接返回"0",因为任何数与0相乘都等于0。

    // 如果num1或num2为"0",则直接返回"0"if (num1.equals("0") || num2.equals("0"))return "0";
    
  2. 获取两个字符串的长度m和n,分别表示num1和num2的位数。

    	// 获取num1的长度mint m = num1.length();// 获取num2的长度nint n = num2.length();
    
  3. 创建一个长度为m+n-1的整型数组intRes,用于存储相乘结果的每一位数字。

    // 创建一个长度为m+n-1的整型数组intRes,用于存储相乘结果的每一位数字int[] intRes = new int[m + n - 1];
    
  4. 使用两层循环遍历num1和num2的每一位数字,将它们相乘的结果累加到intRes数组中对应的位置上。这里需要注意的是,由于num1和num2是字符串表示的整数,所以在计算时需要将字符转换为对应的数字值(通过减去字符’0’的ASCII码值)。

     // 使用两层循环遍历num1和num2的每一位数字for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {// 将num1的第i位数字与num2的第j位数字相乘,然后加上intRes数组中对应位置的值intRes[i + j] += (num1.charAt(i) - 48) * (num2.charAt(j) - 48);}}
    
  5. 对intRes数组进行进位处理。从数组的最后一位开始向前遍历,如果当前位的数字大于等于10,则需要将其除以10加上前一位的值。同时,将当前位的值更新为除以10后的余数

     // 从intRes数组的最后一位开始向前遍历,如果当前位的数字大于等于10,则需要将其除以10并加上前一位的值for (int i = intRes.length - 1; i > 0; i--) {if (intRes[i] >= 10) {intRes[i - 1] += intRes[i] / 10;intRes[i] %= 10;}}
    
  6. 最后,将intRes数组中的每个元素转换为字符串,拼接起来得到最终的相乘结果。拼接起来,形成最终的乘积结果。这个结果被赋值给变量res,并作为方法的返回值。

        // 遍历intRes数组,将每个元素转换为字符串并拼接到res中for (int i = 0; i < intRes.length; i++) {res += String.valueOf(intRes[i]);}// 返回最终的相乘结果return res;}

补充说明

1、为什么在代码思路第3的步骤里,创建一个整型数组intRes是长度为 m+n-1 的呢?

int[] intRes = new int[m + n - 1];

​ 在这段代码中,m + n - 1用于初始化一个长度为m + n - 1的整数数组intRes。这个数组用于存储两个字符串num1和num2相乘的结果

​ 具体来说,如果num1的长度为m,num2的长度为n,那么num1和num2相乘的结果的最大位数就是m + n - 1。

​ 因此,我们需要创建一个长度为m + n - 1的数组来存储结果。

2、在代码思路第4的步骤里,在计算时该怎么将字符转换为对应的数字值呢,又是为什么要减去48呢?

  intRes[i + j] += (num1.charAt(i) - 48) * (num2.charAt(j) - 48);

​ 这段代码的目的是将两个字符串表示的数字相乘,并将结果存储在一个整数数组中。

(num1.charAt(i) - 48)/ (num2.charAt(j) - 48):将num1/num2的第i位字符转换为对应的数字值。

  1. 这里减去48是因为字符’0’的ASCII码值为48
  2. 所以通过减去48可以将字符转换为对应的数字值
  3. (例如,字符’2’的ASCII码值为50,减去48后得到数字2)。

参考代码

这段代码是一个用于实现两个字符串表示的整数相乘的算法。

class Solution {public String multiply(String num1, String num2) {if (num1.equals("0") || num2.equals("0"))return "0";int m = num1.length();int n = num2.length();int[] intRes = new int[m + n - 1];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {intRes[i + j] += (num1.charAt(i) - 48) * (num2.charAt(j) - 48);}}for (int i = intRes.length - 1; i > 0; i--) {if (intRes[i] >= 10) {intRes[i - 1] += intRes[i] / 10;intRes[i] %= 10;}}String res = "";for (int i = 0; i < intRes.length; i++) {res += String.valueOf(intRes[i]);}return res;}
}

子集

题目

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

提示:

1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums 中的所有元素 互不相同

解题思路

  1. 创建一个空的结果列表 res,用于存储所有可能的子集。
  2. 创建一个临时列表 tmp,用于存储当前正在构建的子集。
  3. 将空列表添加到结果列表 res 中。
  4. 如果输入数组 nums 的长度为 0,直接返回结果列表 res。
  5. 调用辅助函数 helper,传入输入数组 nums、起始索引 0、临时列表 tmp 和结果列表 res。
  6. 在辅助函数 helper 中,遍历输入数组 nums 从起始索引 start 开始的所有元素。 a. 将当前元素添加到临时列表 tmp 中。 b. 递归调用辅助函数 helper,传入输入数组 nums、当前元素的下一个索引 i + 1、临时列表 tmp 和结果列表 res。 c. 将当前临时列表 tmp 的副本添加到结果列表 res 中。 d. 移除临时列表 tmp 中的最后一个元素,回溯到上一步。
  7. 返回结果列表 res。

代码思路

  1. 定义一个名为Solution的类,其中包含两个方法:subsetshelper

  2. subsets方法是主方法,它接受一个整数数组nums作为输入,并返回一个包含所有子集的列表。

     public List<List<Integer>> subsets(int[] nums) 
    
  3. subsets方法中,首先创建一个空的结果列表res和一个临时列表tmp,然后将tmp添加到res中。

    List<List<Integer>> res = new ArrayList<List<Integer>>(); // 存储结果的列表List<Integer> tmp = new ArrayList<>(); // 临时列表,用于存储当前子集res.add(tmp); // 将空子集添加到结果列表中
    
  4. 如果输入数组nums的长度为0,则直接返回结果列表res

     if (nums.length == 0) // 如果输入数组为空,直接返回结果列表return res;
    
  5. 调用辅助方法helper,传入输入数组nums、起始索引0、临时列表tmp和结果列表res

       helper(nums, 0, tmp, res); // 调用辅助函数,生成子集
    
  6. helper方法是一个递归方法,用于生成所有可能的子集。它接受四个参数:输入数组nums、当前处理的起始索引start、临时列表tmp和结果列表res

      // 辅助函数,递归生成子集public void helper(int[] nums, int start, List<Integer> tmp, List<List<Integer>> res) 
    
  7. helper方法中,使用一个循环从起始索引start开始遍历输入数组nums

     for (int i = start; i < nums.length; i++)
    
  8. 在每次循环中,将当前元素添加到临时列表tmp中,然后递归调用helper方法,传入下一个索引i + 1、更新后的临时列表tmp和结果列表res

       tmp.add(nums[i]); // 将当前元素添加到临时列表中helper(nums, i + 1, tmp, res); // 递归调用辅助函数,处理下一个元素
    
  9. 在递归调用返回后,将当前的临时列表tmp复制一份,并将其添加到结果列表res中。

    res.add(new ArrayList<Integer>(tmp)); // 将当前临时列表复制一份,添加到结果列表中
    
  10. 最后,从临时列表tmp中移除最后一个元素,以便在下一次循环中处理下一个元素。

       tmp.remove(tmp.size() - 1); // 移除临时列表中的最后一个元素,回溯到上一步
    
  11. 当循环结束时,所有的子集都已经生成并添加到结果列表res中,最终返回该列表。

参考代码

这段代码是一个求解给定数组的所有子集的算法。它使用了回溯法来生成所有可能的子集,并将它们存储在一个列表中返回。

class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> res = new ArrayList<List<Integer>>();List<Integer> tmp = new ArrayList<>();res.add(tmp);if (nums.length == 0)return res;helper(nums, 0, tmp, res);return res;}public void helper(int[] nums, int start, List<Integer> tmp, List<List<Integer>> res) {for (int i = start; i < nums.length; i++) {tmp.add(nums[i]);helper(nums, i + 1, tmp, res);res.add(new ArrayList<Integer>(tmp));tmp.remove(tmp.size() - 1);}}
}

删除链表的倒数第 N 个结点

题目

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

进阶:你能尝试使用一趟扫描实现吗?

示例 1:

image-20231112225051811

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1
输出:[]

示例 3:

输入:head = [1,2], n = 1
输出:[1]

提示:

链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz

解题思路

  1. 创建一个虚拟头节点v,并将其指向原链表的头结点head。这样做的目的是方便处理边界情况,例如当需要删除的是头结点时。
  2. 使用一个循环遍历整个链表,将每个节点添加到一个列表index中。这样我们可以方便地访问链表中的任意节点。
  3. 计算要删除的节点的前一个节点和后一个节点在列表中的索引位置。前一个节点的索引为index.size() - n - 1,后一个节点的索引为index.size() - n + 1
  4. 根据计算出的索引位置,更新前一个节点的next指针,使其指向后一个节点或null(如果后一个节点不存在)。
  5. 返回虚拟头节点v的下一个节点,即删除倒数第n个节点后的链表头结点。

代码思路

  1. 创建一个虚拟头节点v,并将其指向原链表头节点head。这样做是为了方便处理边界情况,例如当需要删除的是头节点时。

     // 移除链表中倒数第n个节点的方法public ListNode removeNthFromEnd(ListNode head, int n) {ListNode v = new ListNode(0, head); // 创建一个虚拟头节点,指向原链表头节点
    
  2. 创建一个名为handle的指针,指向虚拟头节点v。

    ListNode handle = v; // 创建一个指针,指向虚拟头节点
    
  3. 创建一个名为index的列表,用于存储链表中所有节点的引用。

       List<ListNode> index = new ArrayList<>(); // 创建一个列表,用于存储链表中所有节点的引用
    
  4. 使用while循环遍历链表,将每个节点的引用添加到index列表中。

    // 遍历链表,将每个节点的引用添加到列表中while (v != null) {index.add(v);v = v.next;}
    
  5. 计算要删除的节点的前一个节点和后一个节点在index列表中的索引位置pre和next。

      // 计算要删除的节点的前一个节点和后一个节点在列表中的索引位置int pre = index.size() - n - 1;int next = index.size() - n + 1;
    
  6. 根据pre和next的值,更新前一个节点的next指针,使其指向后一个节点或null(如果后一个节点不存在)。

     // 更新前一个节点的next指针,使其指向后一个节点或null(如果后一个节点不存在)index.get(pre).next = next >= 0 && next < index.size() ? index.get(next) : null;
    
  7. 返回处理后的链表头节点handle.next。

             // 返回处理后的链表头节点return handle.next;

参考代码

这段代码是用于删除链表中倒数第n个节点。

public class ListNode {int val;ListNode next;ListNode() {}ListNode(int val) {this.val = val;}ListNode(int val, ListNode next) {this.val = val;this.next = next;}
}
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode v = new ListNode(0, head);ListNode handle = v;List<ListNode> index = new ArrayList<>();while (v != null) {index.add(v);v = v.next;}int pre = index.size() - n - 1;int next = index.size() - n + 1;index.get(pre).next = next >= 0 && next < index.size() ? index.get(next) : null;return handle.next;}
}

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

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

相关文章

【Linux】第十六站:进程地址空间

文章目录 一、程序地址空间1.内存的分布2.static修饰后为什么不会被释放3.一个奇怪的现象 二、进程地址空间1.前面现象的原因2.地址空间究竟是什么&#xff1f;3.为什么要有进程地址空间4.页表5.什么叫进程&#xff1f;6.进程具有独立性。为什么&#xff1f;怎么做到呢&#xf…

解决 Django 开发中的环境配置问题:Windows 系统下的实战指南20231113

简介&#xff1a; 在本文中&#xff0c;我想分享一下我最近在 Windows 环境下进行 Django 开发时遇到的一系列环境配置问题&#xff0c;以及我是如何一步步解决这些问题的。我的目标是为那些可能遇到类似困难的 Django 开发者提供一些指导和帮助。 问题描述&#xff1a; 最近…

2023.11.14-hive之表操作练习和文件导入练习

目录 需求1.数据库基本操作 需求2. 默认分隔符案例 需求1.数据库基本操作 -- 1.创建数据库test_sql,cs1,cs2,cs3 create database test_sql; create database cs1; create database cs2; create database cs3; -- 2.1删除数据库cs2 drop database cs2; -- 2.2在cs3库中创建…

Spark数据倾斜优化

1 数据倾斜现象 1、现象 绝大多数task任务运行速度很快&#xff0c;但是就是有那么几个task任务运行极其缓慢&#xff0c;慢慢的可能就接着报内存溢出的问题。 2、原因 数据倾斜一般是发生在shuffle类的算子&#xff0c;比如distinct、groupByKey、reduceByKey、aggregateByKey…

链表相关部分OJ题

&#x1f493;作者简介&#x1f44f;&#xff1a;在校大二迷茫大学生 &#x1f496;个人主页&#x1f389;&#xff1a;小李很执着 &#x1f497;系列专栏&#xff1a;Leetcode经典题 每日分享&#xff1a;人总是在离开一个地方后开始原谅它❣️❣️❣️———————————…

【Hadoop】MapReduce详解

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f…

nodejs+vue+python+PHP+微信小程序-安卓-房产中介管理信息系统的设计与实现-计算机毕业设计

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

华为笔记本电脑原装win10/win11系统恢复安装教程方法

华为电脑matebook 14原装Win11系统带F10智能还原 安装恢复教程&#xff1a; 1.安装方法有两种&#xff0c;一种是用PE安装&#xff0c;一种是华为工厂包安装&#xff08;安装完成自带F10智能还原&#xff09; 若没有原装系统文件&#xff0c;请在这里获取&#xff1a;https:…

EasyDarwin开源流媒体服务器

文章目录 前言一、EasyDarwin 简介二、EasyDarwin 主要功能特点三、安装部署四、推拉流测试1、进入控制页面2、推流测试3、拉流测试 前言 本文介绍一个十分实用的高性能开源 RTSP 流媒体服务器&#xff1a;EasyDarwin。 一、EasyDarwin 简介 EasyDarwin 是基于 go 语言研发&a…

海康Visionmaster-通讯管理:使用 Modbus TCP 通讯 协议与流程交互

使用 Modbus TCP 通讯协议与视觉通讯&#xff0c;当地址为 0000 的保持型寄存器(4x 寄存器)变为 1 时&#xff0c;触发视觉流程执行一次&#xff0c;同时视觉将地址为 0000 的寄存器复位&#xff08;也即写为 0&#xff09;&#xff0c;视觉流程执行完成后&#xff0c;将结果数…

向量数据库的分类概况

保存和检索矢量数据的五种方法&#xff1a; 像 Pinecone 这样的纯矢量数据库 全文搜索数据库&#xff0c;例如 ElasticSearch 矢量库&#xff0c;如 Faiss、Annoy 和 Hnswlib 支持矢量的NoSQL 数据库&#xff0c;例如 MongoDB、Cosmos DB 和 Cassandra 支持矢量的SQL 数据库&am…

Redis键(Keys)

前言 在 Redis 中&#xff0c;键&#xff08;Keys&#xff09;是非常重要的概念&#xff0c;它们代表了存储在数据库中的数据的标识符。对键的有效管理和操作是使用 Redis 数据库的关键一环&#xff0c;它直接影响到数据的存取效率、系统的稳定性和开发的便利性。 本文将深入…

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(四)

编辑员工和分类模块功能开发 1. 编辑员工1.1 需求分析与设计1.1.1 产品原型1.1.2 接口设计 1.2 代码开发1.2.1 回显员工信息功能1.2.2 修改员工信息功能 1.3 功能测试 2. 分类模块功能开发2.1 需求分析与设计2.1.1 产品原型2.1.2 接口设计2.1.3 表设计 2.2 代码实现2.2.1 Mappe…

HarmonyOS开发(三):ArkTS基础

1、ArkTS演进 Mozilla创建了JS ---> Microsoft创建了TS ----> Huawei进一步推出ArkTS 从最初的基础逻辑交互&#xff08;JS&#xff09;,到具备类型系统的高效工程开发&#xff08;TS&#xff09;,再到融合声明式UI、多维状态管理等丰富的应用开发能力&…

【算法训练-链表 零】链表高频算法题看这一篇就够了

一轮的算法训练完成后&#xff0c;对相关的题目有了一个初步理解了&#xff0c;接下来进行专题训练&#xff0c;以下这些题目就是汇总的高频题目 题目题干直接给出对应博客链接&#xff0c;这里只给出简单思路、代码实现、复杂度分析 反转链表 依据难度等级分别为反转链表、…

Crypto | Affine password 第二届“奇安信”杯网络安全技能竞赛

题目描述&#xff1a; 明文经过仿射函数y3x9加密之后变为JYYHWVPIDCOZ&#xff0c;请对其进行解密&#xff0c;flag的格式为flag{明文的大写形式}。 密文&#xff1a; JYYHWVPIDCOZ解题思路&#xff1a; 1、使用在线网站直接破解或手工计算破解&#xff0c;获得flag。&#xf…

使用Nginx和uwsgi在自己的服务器上部署python的flask项目

Nginx 是一个高性能的 HTTP 和反向代理服务。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力在同类型的网页服务器中表现较好。 Nginx 专为性能优化而开发&#xff0c;性能是其最重要的考量指标&#xff0c;实现上非常注重效率&#xff0c;能经受…

4.CentOS7安装MySQL5.7

CentOS7安装MySQL5.7 2023-11-13 小柴你能看到嘛 哔哩哔哩视频地址 https://www.bilibili.com/video/BV1jz4y1A7LS/?vd_source9ba3044ce322000939a31117d762b441 一.解压 tar -xvf mysql-5.7.26-linux-glibc2.12-x86_64.tar.gz1.在/usr/local解压 tar -xvf mysql-5.7.44-…

lc307.区域和检索 - 数组可修改

暴力解法 创建方法&#xff0c;通过switch-case判断所需要调用的方法。 public class RegionsAndSertches {public static void main(String[] args) {String[] str new String[]{"NumArray", "sumRange", "update", "sumRange"};i…

基于RK3568的跑步机方案

I 方案简介 一、跑步机的来历 跑步机是家庭及健身房常备的健身器材&#xff0c;而且是当今家庭健身器材中最简单的一种&#xff0c;是家庭健身器的最佳选择。1965年北欧芬兰唐特力诞生了全球第一台家用的跑步机&#xff0c;设计师根据传速带的原理改变而成。 二、…