589. N 叉树的前序遍历【简单题】【每日一题】
思路:【递归】
- 定义递归函数recursion,判断当前节点是否为空,如果不是空,那么将当前节点的值添加到 list 中,并挨个遍历其子节点,调用recursion函数对其子节点执行同样的操作;当前节点如果为空,则递归终止,递归函数返回。
- 在preorder函数中,新建列表list,调用recursion函数,最后返回list。
代码:
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public List<Integer> preorder(Node root) {
List<Integer> list = new ArrayList<>();
recursion(list,root);
return list;
}
public void recursion(List<Integer> list , Node root){
if(root == null){
return;
}
list.add(root.val);
for(Node child : root.children){
recursion(list,child);
}
}
}
144. 二叉树的前序遍历【简单题】
思路:【递归】
- 定义递归函数recursion,如果当前节点不为空,则list添加当前节点的值,并依次递归当前节点的左节点和右节点;如果当前节点为空,则递归终止,recursion函数返回。
- 在preorderTraversal函数中,新建列表list,调用递归函数recursion,返回list。
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
recursion(list,root);
return list;
}
public void recursion(List<Integer> list , TreeNode root){
if(root == null){
return;
}
list.add(root.val);
recursion(list,root.left);
recursion(list,root.right);
}
}
2. 两数相加【中等题】
思路:
- 声明链表头head和尾tail,此时两者都为null,定义进位标志位plus,初值为0。
- 只要链表l1和l2有一个不为空,两数相加的过程就继续进行。
- 定义 v1 为 l1 的值,l1为空时 v1=0;定义 v2 为 l2 的值, l2为空时 v2 = 0;定义sum即为两个链表的逆向和,sum = v1+v2+plus;
- 如果头部head为空,即还没有头部,那就创建一个头部,即把头部赋值为当前的sum % 10,同时答案链表只有一个节点,因此头部也是尾部,于是tail = head;
- 如果头部head不为空,说明答案链表已经创建,那么我们只需在答案链表的尾部追加一个尾结点,赋值为当前的sum % 10,并将尾部更新。
- 进位标志位plus更新为 sum / 10;如果链表 l1 当前节点不为空,那么将 l1 更新到下一个节点;如果链表 l2 当前节点不为空,那么将 l2 更新到下一个节点。
- 当 l1 和 l2 同时为空时,说明两个链表相加完毕,此时退出while循环,返回答案链表,即头部为head的链表,即返回head。
代码:
/**
* Definition for singly-linked list.
* 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 addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null,tail = null;
int plus = 0;
while(l1 != null || l2 != null){
int v1 = l1 == null ? 0 : l1.val;
int v2 = l2 == null ? 0 : l2.val;
int sum = v1 + v2 + plus ;
if(head == null){
head = new ListNode(sum % 10);
tail = head;
}else{
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
plus = sum / 10;
if(l1 != null){
l1 = l1.next;
}
if(l2 != null){
l2 = l2.next;
}
}
if(plus > 0){
tail.next = new ListNode(plus);
}
return head;
}
}
93. 复原 IP 地址【中等题】
思路:【回溯】
- 定义回溯函数dfs:
- 有效的IP地址肯定是四段,于是将搜索分为4个部分,用一个长度为4的数组来存放搜索到的合法的ip地址分段,并需要一个id来记录当前搜索到了ip地址的第几段,这个id刚好与存放合法ip地址数组的下标一一对应,另外,在回溯搜索字符串的时候,需要一个变量start来记录当前从什么位置开始搜索字符串。
- 当id等于4时,说明已经搜索到了4个合法的ip地址分段,如果此时字符串的搜索开始位置start=s.length(),说明这四个分段是字符串的ip资质形式的一种有效情况,将这4个分段组成ip地址形式的字符串,添加进list列表中;如果此时字符串的搜索开始位置start
< s.length(),这说明虽然已经找到4个合法分段,但字符串还有字符没有使用,而这种情况是非法的,于是直接return,回溯到上一步。- 当id<4时,如果start = s.length(),说明这4个分段还没找够字符串就遍历完了,那么此时也需要return,回溯到上一步。
- 如果当前数字是0,那么这个ip地址分段只能是0,将当前分段的搜索结果置0之后,开始下一段搜索。
- 上述3种情况排除之后,下面就是最一般的情况,枚举所有可能的ip地址分段:
- 从搜索开始位置start开始,逐个长度截取子串,转为int类型,判断这个分段是否是合法的ip地址分段,(大于0且小于等于255即为合法分段),如果是合法分段,就将当前这个分段地址添加到当前分段位置的segments中,并将要搜索的分段位置即id+1,要搜索的字符位置即start更新为i+1,递归调用dfs函数,查找下一个分段;如果不是合法分段,那么直接直接退出当前循环,回溯到上一层dfs函数中。
代码:
class Solution {
public List<String> restoreIpAddresses(String s) {
List<String> list = new ArrayList<>();
int[] segments = new int[4];
dfs(0,0,s,list,segments);
return list;
}
public void dfs(int id,int start,String s,List<String> list,int[] segments){
if (id == 4){
if (start == s.length()){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {
sb.append(segments[i]);
if (i != 3){
sb.append('.');
}
}
list.add(sb.toString());
}
return;
}
if (start == s.length()){//如果还没找够4段IP地址就已经遍历完了字符串,那么提前回溯
return;
}
if (s.charAt(start) == '0'){//如果当前数字是0,那么这段IP地址只能是0,将当前搜索到的结果赋0之后,直接跳到下一段搜索
segments[id] = 0;
dfs(id+1,start+1,s,list,segments);
}
int addr = 0;
for (int i = start; i < s.length(); i++) {
addr = addr * 10 + (s.charAt(i)-'0');
if (addr > 0 && addr <= 255){
segments[id] = addr;
dfs(id+1,i+1,s,list,segments);
}else {
break;
}
}
}
}