简单
590. N叉树的后序遍历
给定一个 N 叉树,返回其节点值的后序遍历。
例如,给定一个 3叉树 :
返回其后序遍历: [5,6,3,2,4,1].
说明: 递归法很简单,你可以使用迭代法完成此题吗?
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val,List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
List<Integer> list=new ArrayList<Integer>();
//迭代方法
/*public List<Integer> postorder(Node root) {
Stack<Node> stack=new Stack<>();
if(root!=null){
stack.add(root);
}
while(stack.size()>0){
Node node=stack.pop();//出栈
list.add(0,node.val);//头插法
for(Node t:node.children){
stack.add(t);
}
}
return list;
}*/
//递归方法
public List<Integer> postorder(Node root){
postorder(root,list);
return list;
}
public void postorder(Node node,List<Integer> list){
if(node==null){
return;
}
for(Node n:node.children){
postorder(n,list);
}
list.add(node.val);
}
}
589 N叉树的前序遍历
给定一个 N 叉树,返回其节点值的前序遍历。
例如,给定一个 3叉树 :
返回其前序遍历: [1,3,5,6,2,4]。
说明: 递归法很简单,你可以使用迭代法完成此题吗?
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val,List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
List<Integer> list=new ArrayList<>();
//借用栈辅助迭代
/*public List<Integer> preorder(Node root) {
Stack<Node> stack=new Stack<>();
if(root!=null){
stack.add(root);
}
while(stack.size()>0){
Node node=stack.pop();
list.add(node.val);
for(int i=node.children.size()-1;i>=0;i--){
stack.add(node.children.get(i));
}
}
return list;
}*/
public List<Integer> preorder(Node root){
//借用队列辅助迭代
LinkedList<Node> queue=new LinkedList<>();
if(root!=null){
queue.addFirst(root);
}
while(queue.size()>0){
Node node=queue.removeFirst();
list.add(node.val);
queue.addAll(0,node.children);
}
return list;
}
}
递归方法
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val,List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
//递归方法
public List<Integer> preorder(Node root) {
List<Integer> list=new ArrayList<>();
bianLi(root,list);
return list;
}
private void bianLi(Node root,List<Integer> list){
if(root==null){
return;
}
list.add(root.val);
if(root.children!=null){
for(Node node:root.children){
bianLi(node,list);
}
}
}
}
292. Nim游戏
你和你的朋友,两个人一起玩 Nim游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。
你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。
示例:
输入: 4
输出: false
解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛;
因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。
class Solution {
public boolean canWinNim(int n) {
return n%4!=0;
}
}
617. 合并二叉树
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
示例 1:
输入:
Tree 1 Tree 2
1 2
/ \ / \
3 2 1 3
/ \ \
5 4 7
输出:
合并后的树:
3
/
4 5
/ \ \
5 4 7
注意: 合并必须从两个树的根节点开始。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if(t1==null&&t2==null){
return null;
}
TreeNode n=new TreeNode(0);
mergeTrees(n,t1,t2);
return n;
}
private void mergeTrees(TreeNode node,TreeNode t1,TreeNode t2){
if(t1==null&&t2==null){
return ;
}
if(t1!=null&&t2!=null){
node.val=t1.val+t2.val;
if(t1.left!=null||t2.left!=null){
node.left=new TreeNode(0);
mergeTrees(node.left,t1.left,t2.left);
}
if(t1.right!=null||t2.right!=null){
node.right=new TreeNode(0);
mergeTrees(node.right,t1.right,t2.right);
}
}else if(t1!=null&&t2==null){
node.val=t1.val;
if(t1.left!=null){
node.left=new TreeNode(0);
mergeTrees(node.left,t1.left,null);
}
if(t1.right!=null){
node.right=new TreeNode(0);
mergeTrees(node.right,t1.right,null);
}
}else if(t1==null&&t2!=null){
node.val=t2.val;
if(t2.left!=null){
node.left=new TreeNode(0);
mergeTrees(node.left,null,t2.left);
}
if(t2.right!=null){
node.right=new TreeNode(0);
mergeTrees(node.right,null,t2.right);
}
}
}
}
942. 增减字符串匹配
给定只含 “I”(增大)或 “D”(减小)的字符串 S ,令 N = S.length。
返回 [0, 1, …, N] 的任意排列 A 使得对于所有 i = 0, …, N-1,都有:
如果 S[i] == “I”,那么 A[i] < A[i+1]
如果 S[i] == “D”,那么 A[i] > A[i+1]
示例 1:
输出:“IDID”
输出:[0,4,1,3,2]
示例 2:
输出:“III”
输出:[0,1,2,3]
示例 3:
输出:“DDI”
输出:[3,2,0,1]
class Solution {
public int[] diStringMatch(String S) {
int i=0;
int d=S.length();
int[] arr=new int[S.length()+1];
for(int k=0;k<S.length();k++){
arr[k]=S.charAt(k)=='I'?i++:d--;
}
arr[S.length()]=i;
return arr;
}
}
删除链表倒数第n个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null||head.next==null){
return null;
}
ListNode left=head;
ListNode right=head;
for(int i=0;i<n;i++){
right=right.next;
}
if(right==null){
return head.next;
}
while(right.next!=null){
right=right.next;
left=left.next;
}
left.next=left.next.next;
return head;
}
}
206 反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
递归法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
//递归
if(head==null||head.next==null){
return head;
}
ListNode h=reverseList(head.next);
head.next.next=head;
head.next=null;
return h;
/* if(head==null||head.next==null){
return head;
}
ListNode root=new ListNode(0);
ListNode n=root;
while(head!=null){
n=head;
head=head.next;
n.next=root.next;
root.next=n;
}
return root.next;*/
}
}
203删除链表元素
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
ListNode p=new ListNode(0);
ListNode cur=p;
while(head!=null){
if(head.val!=val){
cur.next=head;
head=head.next;
cur=cur.next;
cur.next=null;
}else{
head=head.next;
}
}
return p.next;
}
}
328奇偶链表
给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
示例 1:
输入: 1->2->3->4->5->NULL
输出: 1->3->5->2->4->NULL
示例 2:
输入: 2->1->3->5->6->4->7->NULL
输出: 2->3->6->7->1->5->4->NULL
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode oddEvenList(ListNode head) {
if(head==null){
return head;
}
ListNode ji=head;
ListNode ou=head.next;
ListNode ouStart=head.next;
while(ou!=null&&ou.next!=null){
ji.next=ji.next.next;
ou.next=ou.next.next;
ou=ou.next;
ji=ji.next;
}
ji.next=ouStart;
return head;
}
}
234回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
ListNode mid=findMid(head);
ListNode h=head;
ListNode p=reverse(mid.next);
while(p!=null&&h.val==p.val){
p=p.next;
h=h.next;
}
return p==null;
}
private ListNode findMid(ListNode head){
if(head==null){
return null;
}
ListNode slow=head;
ListNode fast=head.next;
while(fast!=null&&fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
return slow;
}
private ListNode reverse(ListNode head){
if(head==null||head.next==null){
return head;
}
ListNode h=reverse(head.next);
head.next.next=head;
head.next=null;
return h;
}
}
21合并两个有序链表
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode h1=l1;
ListNode h2=l2;
ListNode h=new ListNode(0);
ListNode cur=h;
while(h1!=null&&h2!=null){
if(h1.val<=h2.val){
cur.next=h1;
h1=h1.next;
}else{
cur.next=h2;
h2=h2.next;
}
cur=cur.next;
cur.next=null;
}
if(h1!=null){
cur.next=h1;
}
if(h2!=null){
cur.next=h2;
}
return h.next;
}
}
2两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode h=new ListNode(0);
ListNode p=h;
int carry=0;
while(l1!=null||l2!=null||carry==1){
int num=((l1==null)?0:l1.val)+((l2==null)?0:l2.val)+carry;
ListNode n=new ListNode(num%10);
p.next=n;
p=p.next;
carry=num/10;
l1=(l1==null)?null:l1.next;
l2=(l2==null)?null:l2.next;
}
return h.next;
}
}
724寻找数组的中心索引
给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。
我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
示例 1:
输入:
nums = [1, 7, 3, 6, 5, 6]
输出: 3
解释:
索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
同时, 3 也是第一个符合要求的中心索引。
class Solution {
public int pivotIndex(int[] nums) {
int len=nums.length;
if(len==1){
return 0;
}
int sum=0;
int left=0;
int right=0;
for(Integer num:nums){
sum+=num;
}
for(int i=0;i<len;i++){
if(i==0){
left=0;
}else{
left+=nums[i-1];
}
right=sum-left-nums[i];
if(left==right){
return i;
}
}
return -1;
}
}
66 加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:
输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
class Solution {
public int[] plusOne(int[] digits) {
int carry=0;
for(int i=digits.length-1;i>=0;i--){
if(carry==1||(i==digits.length-1)){
int num=digits[i]+1;
carry=num/10;
num=num%10;
digits[i]=num;
}
}
if(carry==1){
int[] newArr=new int[digits.length+1];
for(int j=0;j<digits.length;j++){
newArr[j+1]=digits[j];
}
digits=newArr;
digits[0]=1;
}
return digits;
}
}
169 求众数
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在众数。
示例 1:
输入: [3,2,3]
输出: 3
示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2
class Solution {
public int majorityElement(int[] nums) {
int max=nums[0];
int count=1;
for(int i=0;i<nums.length;i++){
if(max==nums[i]){
count++;
}else{
count--;
if(count==0){
max=nums[i];
count=1;
}
}
}
return max;
}
}
中等
240搜索二维矩阵
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int i=matrix.length-1;
int j=0;
if(matrix==null||matrix.length<1||matrix[0].length<1){
return false;
}
while(true){
if(target==matrix[i][j]){
return true;
}else if(target<matrix[i][j]){
i--;
}else if(target>matrix[i][j]){
j++;
}
if(i<0||j==matrix[0].length){
break;
}
}
return false;
}
}
54螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例 1:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
示例 2:
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]
自己的做法
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list=new ArrayList<Integer>();
if(matrix==null||matrix.length<1){
return list;
}
int left=0;
int right=matrix[0].length-1;
int up=0;
int down=matrix.length-1;
int count=0;
while(left!=right||up!=down){
//向右
if(up!=down){
for(int i=left;i<=right;i++){
list.add(matrix[up][i]);
count++;
}
up++;
}else{
for(int i=left;i<=right;i++){
list.add(matrix[up][i]);
count++;
}
break;
}
//向下
if(left!=right){
for(int i=up;i<=down;i++){
list.add(matrix[i][right]);
count++;
}
right--;
}else{
for(int i=up;i<=down;i++){
list.add(matrix[i][right]);
count++;
}
break;
}
//向左
if(up!=down){
for(int i=right;i>=left;i--){
list.add(matrix[down][i]);
count++;
}
down--;
}else{
for(int i=right;i>=left;i--){
list.add(matrix[down][i]);
count++;
}
break;
}
//向上
if(left!=right){
for(int i=down;i>=up;i--){
list.add(matrix[i][left]);
count++;
}
left++;
}else{
for(int i=down;i>=up;i--){
list.add(matrix[i][left]);
count++;
}
break;
}
}
if(count!=matrix.length*matrix[0].length){
list.add(matrix[up][left]);
}
return list;
}
}
用一个二维状态数组做辅助
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> list=new ArrayList<Integer>();
if(matrix==null||matrix.length==0){
return list;
}
int row=matrix.length;
int col=matrix[0].length;
int count=row*col;
boolean[][] flag=new boolean[row][col];//状态数组
int x=0;
int y=0;
while(true){
if(count==list.size()){
break;
}
//向右
while(x<col&&!flag[y][x]){
list.add(matrix[y][x]);
flag[y][x]=true;
x++;
}
x--;
y++;
//向下
while(y<row&&!flag[y][x]){
list.add(matrix[y][x]);
flag[y][x]=true;
y++;
}
y--;
x--;
//向左
while(x>=0&&!flag[y][x]){
list.add(matrix[y][x]);
flag[y][x]=true;
x--;
}
x++;
y--;
//向上
while(y>=0&&!flag[y][x]){
list.add(matrix[y][x]);
flag[y][x]=true;
y--;
}
y++;
x++;
}
return list;
}
}
173. 二叉搜索树迭代器
实现一个二叉搜索树迭代器。你将使用二叉搜索树的根节点初始化迭代器。
调用 next() 将返回二叉搜索树中的下一个最小的数。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class BSTIterator {
Stack<TreeNode> stack=new Stack<>();
public BSTIterator(TreeNode root) {
TreeNode cur=root;
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
}
/** @return the next smallest number */
public int next() {
TreeNode n=stack.pop();
TreeNode cur=n.right;
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
return n.val;
}
/** @return whether we have a next smallest number */
public boolean hasNext() {
return stack.size()!=0;
}
}
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/