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…

问题复盘|MySQL 数据记录中明明有值,使用 concat() 后得到的却一直是 null

背景 MySQL 的数据数据记录中明明有值&#xff0c;在使用 concat() 查询时却一直得到 null SELECT CONCAT(first_name, , last_name) FROM users;排查后发现 MySQL 的 concat 函数拼接规则是 当多个拼接的字段的字段值中存在 null 时&#xff0c;返回的一定是 null 解决方…

【算法】算法题-20231114

这里写目录标题 一、LCR 181. 字符串中的单词反转二、557. 反转字符串中的单词 III三、344. 反转字符串四、给定一个已按照升序排列的有序数组&#xff0c;找到两个数使得它们相加之和等于目标数。五、力扣第49题&#xff1a;字母异位词分组 一、LCR 181. 字符串中的单词反转 …

解决 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库中创建…

optee4.0.0 qemu_v8环境搭建(支持Hafnium)

安全之安全(security)博客目录导读 目录 一、前提条件 二、拉取代码 三、下载工具链 四、编译 五、运行

了解防抖和节流:提升前端交互体验的实用策略

了解防抖和节流&#xff1a;提升前端交互体验的实用策略 前言什么是防抖&#xff1f;什么是节流&#xff1f;应用实例防抖实例节流实例 前言 本文将重点介绍前端性能优化方法之一的防抖和节流。首先解释了它们的概念和原理&#xff0c;然后探讨了它们在前端开发中的应用场景&a…

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;人总是在离开一个地方后开始原谅它❣️❣️❣️———————————…

pgsql_全文检索_使用空间换时间的方法支持中文搜索

pgsql_全文检索_使用空间换时间的方法支持中文搜索 一、环境 PostgreSQL 14.2, compiled by Visual C build 1914, 64-bit 二、引言 提到全文检索首先想到的就是ES(ElasticSearch)和Lucene&#xff0c;专业且强大。对于一些小众场景对于搜索要求不高&#xff0c;数据量也不…

10 Go的映射

概述 在上一节的内容中&#xff0c;我们介绍了Go的结构体&#xff0c;包括&#xff1a;定义结构体、声明结构体变量、使用结构体、结构体关联函数、new、组合等。在本节中&#xff0c;我们将介绍Go的映射。Go语言中的映射&#xff08;Map&#xff09;是一种无序的键值对集合&am…

【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;它直接影响到数据的存取效率、系统的稳定性和开发的便利性。 本文将深入…

如何将本地项目推送到gitee仓库

本地项目推送到gitee仓库的两种方式&#xff1a; 一、新建gitee空仓库&#xff0c;然后git clone到本地&#xff0c;然后把代码复制进去提交 1.在gitee创建一个仓库&#xff0c;然后git clone 新建的仓库地址&#xff0c;到本地&#xff1b; 2.把项目代码复制到clone下来的仓…

基于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…