LeetCode -- 之字形二叉树、大数加法、删除链表的倒数第N个数

109 阅读2分钟

今天是记录leetcode刷题的第八天了,今天手感不错,效率很好,估计是周末休息的很好。

今天的题目是:之字形二叉树、大数加法、删除链表的倒数第N个数,一共三个题,难度都在中等,当然还有一个比较熟悉的层序二叉树遍历的变形。

之字形打印二叉树

题目要求如下

给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)

这道题还算是比较简单的,因为我们上次写的时候,每层都会生成一个ArrayList的层序数组,这次我们只需要在将其放入返回数组时,对其判断,如果是偶数层就不变,如果是奇数层就反转(reverse)。

代码如下:

import java.util.*;

public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
       // 层序遍历,队列
        if(pRoot == null){
            return new ArrayList<ArrayList<Integer>>();
        }
        ArrayDeque<TreeNode> deque = new ArrayDeque<>();
        deque.offer(pRoot);
        ArrayList<ArrayList<Integer>> rt = new ArrayList<>();
        // 层数
        int levelNum = 0;
        while (deque.size() > 0) {
            int size = deque.size();
            ArrayList<Integer> level = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                TreeNode tmp = deque.poll();
                if (tmp.left != null) {
                    deque.offer(tmp.left);
                }
                if (tmp.right != null) {
                    deque.offer(tmp.right);
                }
                level.add(tmp.val);
            }
            if (levelNum % 2 == 0) {
                rt.add(level);
            } else {
                rt.add(reverse(level));
            }
            levelNum++;
        }
        return rt;
    }

    public ArrayList<Integer> reverse(ArrayList<Integer> level) {
        int size = level.size();
        ArrayList<Integer> rt = new ArrayList<>(size);

        while (size > 0) {
            rt.add(level.get(size - 1));
            size--;
        }
        return rt;
    }
    
    public class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int val) {
            this.val = val;
        }
    }
}

大数加法

题目要求如下

以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。

数据范围:s.length,t.length≤100000,字符串仅由'0'~‘9’构成

要求:时间复杂度 O(n)

这道题更像是双指针问题,我们需要从字符串的最后一位开始相加,和大于10则进位,不大于10则直接放到相应的位上。

代码如下

public String solve(String s, String t) {
    // write code here
    int len1 = s.length();
    int len2 = t.length();
    int max = Math.max(len1, len2);
    // 为进位预留一个空间
    char[] sum = new char[max + 1];

    //进位
    int carry = 0;
    // 辅助指针,
    int index = 0;
    for (int i = max; i >= 0; i--,index++) {
        int ad = carry;

        if (index < len1) {
            ad += (s.charAt(len1 - index - 1) - 48);
        }
        if (index < len2) {
            ad += (t.charAt(len2 - index - 1) - 48);
        }
        sum[i] = (char) (ad % 10 + 48);

        // 更新carry,进位
        carry = ad / 10;
    }

    //拼接字符串
    StringBuilder sb = new StringBuilder(max + 1);
    for (char c : sum) {
        sb.append(c);
    }
    String rt = sb.toString();
    // 去掉前面无效的0
    if (rt.startsWith("0")) {
        rt = rt.substring(1);
    }
    return rt;
}

当然,Java自带大数类(BigInteger.java),也可以直接使用这个类来运算,这样这道题就会显得很简单很简单了,但是效率不是很高。

public String solve1 (String s, String t) {
    // 大数类构造方法
    BigInteger bi1 = new BigInteger(s);
    BigInteger bi2 = new BigInteger(t);
    bi1 = bi1.add(bi2);
    return bi1.toString();
}

删除链表的倒数第N个数

题目要求如下

给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针

例如,

给出的链表为: 1→2→3→4→5, n= 2

删除了链表的倒数第 n 个节点之后,链表变为1→2→3→5.

这又是一道双指针问题,我们需要先知道链表的长度size,在我们得到链表的size后,这道题就变成了寻找第(size - n + 1)个节点的前置节点。

代码如下

public ListNode removeNthFromEnd (ListNode head, int n) {
    // write code here
    int size = getSize(head);
    ListNode tmp = new ListNode(0);
    ListNode pre = tmp;
    pre.next = head;
    int index = 0;
    // 找到第size - n + 1 个的前一个,从0开始

    while(size - index > n) {
        // 找到pre
        pre = pre.next;
        index++;
    }
    pre.next = pre.next.next;
    return tmp.next;
}

public int getSize(ListNode head) {
    int size = 0;
    while(head != null) {
        size++;
        head = head.next;
    }
    return size;
}