运算问题

132 阅读4分钟

微信图片_20230703112438.png

2. 两数相加

image.png

解法

  1. 这个题目做了无数遍了,是能够确定掌握的题目之一。
  2. 要注意两点:一是判空,因为两个链表长度不一,二是,要注意进位。

复杂度:时间O(n) | 空间O(1)

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode x1 = l1;
        ListNode x2 = l2;
        int mod = 0;
        ListNode l3 = new ListNode();
        ListNode head = l3;
        while (x1 != null || x2 != null || mod != 0) {
            int val1 = x1 == null ? 0 : x1.val;
            int val2 = x2 == null ? 0 : x2.val;
            int sum = val1 + val2 + mod;
            l3.next = new ListNode(sum % 10);
            mod = (sum) / 10;
            if (x1 != null) {
                x1 = x1.next;
            }
            if (x2 != null) {
                x2 = x2.next;
            }
            l3 = l3.next;
        }
        return head.next;

    }
}

206. 反转链表

image.png

解法

递归和顺序的都要掌握。

(1)迭代

必然要用到多指针。

复杂度:时间O(n) | 空间O(1)

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode p, q, r;
        p = null;
        q = head;
        r = q.next;
        while (q != null) {
            // 反转,因为每次只走一步,所以,每次只做一次反转动作
            q.next = p;
            // 让指针往前走
            p = q;
            q = r;
            if (r != null) {
                r = r.next;
            }
        }
        return p;
    }
}

(2)递归

递归反正每次都写不出来。

复杂度:时间O(n) | 空间O(n),因为栈需要存储元素。

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
}

445. 两数相加 II

和第一题差不多,区别在于第一题是逆序,这一题是正序。

image.png

解法

先将两个链表翻转,再相加合并,然后再翻转返回。

复杂度:时间O(n) | 空间O(m+n)

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode x1 = reverseList(l1);
        ListNode x2 = reverseList(l2);
        return reverseList(addTwoNums(x1, x2));
    }

    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }

    public ListNode addTwoNums(ListNode l1, ListNode l2) {
        ListNode x1 = l1;
        ListNode x2 = l2;
        int mod = 0;
        ListNode l3 = new ListNode();
        ListNode head = l3;
        while (x1 != null || x2 != null || mod != 0) {
            int val1 = x1 == null ? 0 : x1.val;
            int val2 = x2 == null ? 0 : x2.val;
            int sum = val1 + val2 + mod;
            l3.next = new ListNode(sum % 10);
            mod = (sum) / 10;
            if (x1 != null) {
                x1 = x1.next;
            }
            if (x2 != null) {
                x2 = x2.next;
            }
            l3 = l3.next;
        }
        return head.next;
    }
}

989. 数组形式的整数加法

image.png

解法

class Solution {
    public List<Integer> addToArrayForm(int[] num, int k) {
        List<Integer> result = new LinkedList<>();
        int len = num.length;
        for (int i = len - 1; i >= 0; i--) {
            int sum = num[i] + k % 10;
            k /= 10;
            if (sum >= 10) {
                k++;
                sum = sum % 10;
            }
            result.addFirst(sum);
        }
        for (; k > 0; k = k / 10) {
            result.addFirst(k % 10);
        }
        return result;
    }
}

这个应该是数字运算进位的常用思路,要记住的。 直接用k个num里的每一位相加,然后取余留给当前位置,除10给进位。

class Solution {
    public List<Integer> addToArrayForm(int[] num, int k) {
        List<Integer> result = new LinkedList<>();
        int len = num.length;
        for (int i = len - 1; i >= 0 || k > 0; i--, k = k / 10) {
            if (i >= 0) {
                k = k + num[i];
            }
            result.addFirst(k % 10);
        }
        return result;
    }
}

344. 反转字符串

image.png

要求必须原地翻转,只可以使用O(1)的空间

解法

太简单了,不提。

class Solution {
    public void reverseString(char[] s) {
        int left = 0;
        int right = s.length - 1;
        while (left < right) {
            swap(s, left++, right--);
        }
    }

    public void swap(char[] s, int left, int right) {
        char tmp = s[left];
        s[left] = s[right];
        s[right] = tmp;
    }
}

415. 字符串相加

image.png

字符串反转,可以使用StringBuilder

class Solution {
    public String addStrings(String num1, String num2) {
        int len1 = num1.length();
        int len2 = num2.length();
        int l1 = len1 - 1;
        int l2 = len2 - 1;
        int mod = 0;
        StringBuilder result = new StringBuilder();
        while (l1 >= 0 || l2 >= 0 || mod > 0) {
            int v1 = l1 >= 0 ? num1.charAt(l1) - '0' : 0;
            int v2 = l2 >= 0 ? num2.charAt(l2) - '0' : 0;
            int sum = v1 + v2 + mod;
            mod = sum / 10;
            if (sum >= 10) {
                sum %= 10;
            }
            result.append(sum);
            l1--;
            l2--;
        }
        result.reverse();
        return result.toString();
    }
}

43. 字符串相乘

解法

  1. 直接用乘法运算。计算每一位之间的乘积,将结果相加,放入数组中。
  2. 得到的乘积最多为m+n位。
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[] result = new int[m + n];
        for (int i = m - 1; i >= 0; i--) {
            int v1 = num1.charAt(i) - '0';
            for (int j = n - 1; j >= 0; j--) {
                int v2 = num2.charAt(j) - '0';
                result[i + j + 1] += v1 * v2;
            }
        }
        for (int k = m + n - 1; k > 0; k--) {
            int val = result[k];
            result[k] = val % 10;
            result[k - 1] += val / 10;
        }
        int index = result[0] == 0 ? 1 : 0;
        StringBuilder sb = new StringBuilder();
        while (index < m + n) {
            sb.append(result[index++]);
        }
        return sb.toString();
    }
}

67. 二进制求和

解法

也是很简单,十进制转化为二进制运算就行了。

class Solution {
    public String addBinary(String a, String b) {
        int m = a.length() - 1;
        int n = b.length() - 1;
        int mod = 0;
        StringBuilder sb = new StringBuilder();
        while (m >= 0 || n >= 0 || mod != 0) {
            int val1 = m >= 0 ? a.charAt(m) - '0' : 0;
            int val2 = n >= 0 ? b.charAt(n) - '0' : 0;
            int sum = val1 + val2 + mod;
            mod = sum / 2;
            if (sum == 2) {
                sb.append("0");
            } else if (sum == 3) {
                sb.append("1");
            } else {
                sb.append(sum);
            }
            m--;
            n--;
        }
        sb.reverse();
        return sb.toString();
    }
}