今天是记录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;
}