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.hqwc.cn/news/174847.html

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

相关文章

光刻机ASML CYMER光电模块组件维修114122,S111310

1&#xff1a;436nm g-line 可以满足0.8-0.35 微米制程芯片的生产&#xff0c;对应设备有接触式和接近式光刻机。 2&#xff1a;365nm i-line 同样可以满足0.8~0.35微米制程芯片的生产。设备于上相同。 早期的光刻机采用接触式光刻&#xff0c;即掩模贴在硅片上进行光刻&…

【MongoDB】索引 – 通配符索引

一、准备工作 这里准备一些数据 db.books.drop();db.books.insert({_id: 1, name: "Java", alias: "java 入门", description: "入门图书" }); db.books.insert({_id: 2, name: "C", alias: "c", description: "C 入…

C语言--数组的长度计算【详细解释】

一.数组的长度计算公式 我们都知道字符串有特定的函数strlen,而数组没有&#xff0c;&#xff08;虽然字符串也是一种特殊的数组&#xff09; 但是&#xff0c;类似于这样的数组&#xff1a; int arr[]{12,89,1,5,31,78,45,12,12,0,45,142,21,12}&#xff1b; 我们很难一眼…

数据结构----顺序栈的操作

1.顺序栈的存储结构 typedef int SElemType; typedef int Status; typedef struct{SElemType *top,*base;//定义栈顶和栈底指针int stacksize;//定义栈的容量 }SqStack; 2.初始化栈 Status InitStack(SqStack &S){//初始化一个空栈S.basenew SElemType[MAXSIZE];//为顺序…

腾讯云2核4G服务器CVM标准型S5实例租用5年价格表

腾讯云服务器网整理五年云服务器活动 txyfwq.com/go/txy 配置可选2核4G和4核8G&#xff0c;公网带宽可选1M、3M或5M&#xff0c;系统盘为50G高性能云硬盘&#xff0c;标准型S5实例CPU采用主频2.5GHz的Intel Xeon Cascade Lake或者Intel Xeon Cooper Lake处理器&#xff0c;睿频…

Transformer模型

目录 1. 概述 2. Model Architecture 2.1 自回归 2.2 编码器与解码器 2.3 Attention 2.4 Attention—mask 2.5 Multi-Head Attention 2.6 自注意力使用 2.7 point-wise feed forward network 2.8 embeddings 2.9 positional Encoding 1. 概述 之前的模型&#xf…

Shiro快速入门之三

一、前言 接Shiro快速入门之二&#xff0c;上篇侧重于介绍认证&#xff0c;这篇介绍一下Shiro的授权&#xff0c;先初始化5张表的数据。 注&#xff1a;创建三条权限记录&#xff0c;一个admin角色分配查询和添加用户权限&#xff0c;一个账户qingcai18036授予管理员角色。 二…

数据结构:串(定义,基本操作,存储结构)

目录 1.串的定义2.串的基本操作3.字符集编码4.串的存储结构1.顺序存储2.链式存储 1.串的定义 串&#xff0c;即字符串( String&#xff09;是由零个或多个字符组成的有限序列。 一般记为s ‘a1a2……an’ (n ≥0) 其中&#xff0c;S是串名&#xff0c;单引号括起来的字符序列是…

FCOS难点记录

FCOS 中有计算 特征图&#xff08;Feature map中的每个特征点到gt_box的左、上、右、下的距离&#xff09; 1、特征点到gt_box框的 左、上、右、下距离计算 x coords[:, 0] # h*w&#xff0c;2 即 第一列y coords[:, 1] l_off x[None, :, None] - gt_boxes[..., 0][:, No…

使用U盘安装ubuntu22操作教程

U盘启动 将烧录好的U盘&#xff0c;插上待安装系统的电脑 服务器在开机之后长按【ESC键】进入BIOS选项中&#xff0c;选择对应的U盘启动 如下图&#xff0c;在界面中“USB”选项就是我的U盘&#xff0c;第一启动项选择U盘启动&#xff0c;其他启动项不动&#xff0c;选择后按F…

【推荐】一款AI写作大师、问答、绘画工具-「智元兔 AI」

在当今技术飞速发展的时代&#xff0c;越来越多的领域开始应用人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;。其中&#xff0c;AI写作工具备受瞩目&#xff0c;备受推崇。在众多的选择中&#xff0c;智元兔AI是一款在笔者使用过程中非常有帮助的…

使用gitflow时如何合并hotfix

前言 在使用 git flow 流程时, 对于项目型的部署项目经常会遇到一个问题, 就是现场项目在使用历史版本时发现的一些问题需要修复, 但升级可能会有很大的风险或客户不愿意升级, 这时就要求基于历史版本进行 hotfix 修复. 基于历史发布版本的缺陷修复方式不同于最新发布版本的补…