2 つの負でない整数を表す 2 つの空でない連結リストが与えられます。それぞれの数字は逆順で保存され、各ノードは 1 つの数字しか保存できません。
2 つの数値を加算し、同じ形式で合計を表す連結リストを返してください。
ゼロ以外のゼロで始まる数字はないと仮定できます。
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
これは非常に古典的な連結リストの問題であり、アナログ加算で解決できます。具体的には, キャリーを表す変数のキャリーを維持し, 次に2つのリンクされたリストに対応するノードを追加し, キャリーのキャリーを追加します. 最終結果は現在の位置の数です. 10を超える場合は, キャリーする必要があります.は 1 に設定され、それ以外の場合は 0 に設定されます。
具体的な操作手順は次のとおりです。
1. 最初に空のノード ダミーとポインタ p を定義します。これらは、結果リンク リストの先頭ノードと現在のノードを表します。
2. 2 つのリンクされたリストのヘッド ノードをそれぞれ指す 2 つのポインター p1 および p2 を定義し、リンクされたリストの 1 つが空になるまでそれらをトラバースします。
3. ループでは、まず現在の位置の数値を計算し、次にこの数値を格納する新しいノードを作成して、結果リストの最後に追加します。同時にキャリー値を更新します。
4. リンクされたリストがトラバースされた場合、別のリンクされたリストの残りの部分を追加し、結果のリンクされたリストに順番に運ぶ必要があります。
5. 最後に、ダミーの次のノードに戻ります。
コードは次のように実装されます。
package com.example.算法;
public class ListNode1 {
public static void main(String[] args) {
//创建两个链表l1和l2(此处省略创建过程)
ListNode1 l1 = new ListNode1(2, new ListNode1(4, new ListNode1(3)));
ListNode1 l2 = new ListNode1(5, new ListNode1(6, new ListNode1(4)));
//调用addTwoNumbers函数计算结果
ListNode1 result = addTwoNumbers(l1, l2);
//遍历并输出新链表中的每个节点值
while (result != null) {
System.out.print(result.val + " ");
result = result.next;
}
}
int val;
ListNode1 next;
ListNode1() {
}
ListNode1(int val) {
this.val = val;
}
ListNode1(int val, ListNode1 next) {
this.val = val;
this.next = next;
}
public static ListNode1 addTwoNumbers(ListNode1 l1, ListNode1 l2) {
ListNode1 dummy = new ListNode1(0); // 这里需要用到哑结点技巧
ListNode1 tail = dummy; // 定义一个尾指针,用于构建答案链表
int carry = 0; // 进位信息,初始值为0
while (l1 != null || l2 != null) {
int x = (l1 != null) ? l1.val : 0;
int y = (l2 != null) ? l2.val : 0;
int sum = carry + x + y;
carry = sum / 10; // 更新进位信息
tail.next = new ListNode1(sum % 10); // 构造答案链表的下一个节点
tail = tail.next; // 将尾指针向后移动一位
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (carry > 0) {
tail.next = new ListNode1(carry); // 处理最高位的进位
}
return dummy.next; // 返回哑结点的下一个节点,即为所求的答案链表
}
}
一般的な方法
package com.example.算法;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.Collections.replaceAll;
public class ListNode {
public static void main(String[] args) {
final int l1 = 9999999;
final int l2 = 9999;
int carry = 0;
String a = new Demo().lee(l1, l2);
System.out.println("------------------------------------");
String a2 = new Demo().lee3(l1, l2);
System.out.println("------------------------------------");
Double aa = 1003.0;
aa = aa / 10;
System.out.println(aa);
int abc = aa.intValue();
System.out.println(abc);
}
}
class Demo {
public String lee(int l1, int l2) {
int num = l1 + l2;
// 反转后的数字
int reverseNum = 0;
// 反向遍历每一位数字
while (num != 0) {
int digit = num % 10; //10的余数可以理解为取最后个位数
// System.out.println("现在的digit代表着个位数" + digit);
reverseNum = reverseNum * 10 + digit; // 将个位数添加到反转数中
num /= 10; // 去掉已处理的最后一位数
}
// 将反转后的数字转换成字符串形式
String nums = Integer.toString(reverseNum);
// 创建一个 StringBuffer 对象,用于拼接结果字符串
StringBuffer sb = new StringBuffer();
for (int i = 0; i < nums.length(); i++) {
//append 拼接字符串 nums.charAt(i) 先拿到其中的每一位
sb.append(nums.charAt(i));
// 如果不是最后一位数字,则在数字之间添加一个逗号
if (i != nums.length() - 1) {
sb.append(",");
}
}
// 将 StringBuffer 对象转换成字符串,并返回结果
String fa = sb.toString();
System.out.println("输出:1[" + fa + "]");
return fa;
}
public String lee3(int l1, int l2) {
int num = l1 + l2;
List<Integer> digits = new ArrayList<>();
// 取出每一位数字并添加到列表中
while (num > 0) {
//余数可以理解为取最后个位数 相当于把数据倒序了下取出来 num%10 取出来个位数 add 给了digits 下面再把已经add的数据删除了
digits.add(num % 10);
//再取消最后一位 把上面num % 10
num /= 10;
}
// 将列表中的数字反转并拼接成字符串
//首先使用stream()方法将整数列表转换为流,然后使用map()方法将每个整数转换为字符串形式。Object::toString
// 表示将每个对象(包括整数)转换为它的字符串表示形式。最后,使用collect()方法与Collectors.joining()静态方法结合使用,
// 使用逗号连接符将所有字符串组合在一起,并返回拼接后的字符串。
String fa = digits.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
System.out.println("输出3:[" + fa + "]");
return fa;
}
}
これは、主に 2 つの整数の加算を実装し、結果を文字列として逆順に出力する Java コードです。これを実現するために、コードでは 2 つの異なる方法が使用されます. 最初の方法では、各桁は剰余と除算によって逆にトラバースされ、逆数に追加されます. 2 番目の方法では、最初に 計算された数値をリストに格納します. 、リスト内の数値を逆にして連結して文字列にします。最後に、main() メソッドを呼び出すことで、プログラムの出力を取得できます。
具体的には、コードには次の重要な部分が含まれています。
2 つの整数の加算
2 つの定数 l1 と l2 がコードで定義されており、それぞれ加算する必要がある 2 つの整数を表します。それらを合計すると、2 つの数値の合計である num の値が得られます。
final int l1 = 9999999;
final int l2 = 9999;
int num = l1 + l2;
各桁の逆走査
数値を逆順に出力するために、コード内で while ループ文を使用して num を逆走査します。各ループで、10 を法として num の最後の桁を取得し、reverseNum に追加します。次に、10 で割って、処理された最後の桁を削除します。num が 0 の場合、すべての数値が処理され、ループが終了したことを意味します。
while (num != 0) {
int digit = num % 10;
reverseNum = reverseNum * 10 + digit;
num /= 10;
}
数値を文字列に変換して出力する
コードでは、最初に反転した数値 reverseNum を文字列形式の nums に変換し、次に各桁をトラバースし、数値の間にカンマを追加して、結果を StringBuffer オブジェクト sb middle に追加します。最後に、sb が文字列 fa に変換されて返されます。
String nums = Integer.toString(reverseNum);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < nums.length(); i++) {
sb.append(nums.charAt(i));
if (i != nums.length() - 1) {
sb.append(",");
}
}
String fa = sb.toString();
System.out.println("输出:1[" + fa + "]");
return fa;
ストリーム操作を使用して数値を反転し、それらを文字列に結合する
別のメソッド lee3 がコード内で定義されており、以前のメソッド lee と比較して、Java8 の新しいストリーム操作を使用して実現します。具体的には、コードは最初に計算された数値 num の各桁をリスト digits に追加し、次に stream()、map()、collect() などのメソッドを使用してリスト内の数値を反転し、文字列に連結します。最後に、つなぎ合わせた文字列 fa を返します。
List<Integer> digits = new ArrayList<>();
while (num > 0) {
digits.add(num % 10);
num /= 10;
}
String fa = digits.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
System.out.println("输出3:[" + fa + "]");
return fa;
一般に、このコードは 2 つの異なるメソッドを使用して 2 つの整数を加算し、結果を文字列として逆順で出力します。その中でも、剰余演算と除算演算を介して各桁を逆にたどる方法はより直感的で理解しやすく、ストリーム演算を使用した実装はより簡潔で効率的です。さまざまな方法には独自の利点と適用可能なシナリオがあり、特定の状況に応じて選択できます。
最初の方法では、コードは while ループを介して整数の各桁を反復処理し、それを逆数に加算します。次に、逆数を文字列に変換し、その中の各数字を反復処理し、数字の間にコンマを追加して、文字列として出力します。
2 番目のアプローチでは、コードは最初に計算された数値の各桁をリストに追加し、次にストリーム操作を使用してリスト内の数値を逆にし、文字列に連結します。
全体として、このコードは Java で同じ目標を達成するためのさまざまなアプローチを示し、それらの利点と使用例を説明しています。