剑03.数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0 ~n- 1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1 :
输入:
[ 2 , 3 , 1 , 0 , 2 , 5 , 3 ]
输出:2 或 3
public class Solution {
public int findRepeatNumber ( int [ ] nums) {
HashSet< Integer> set = new HashSet < > ( ) ;
for ( int i = 0 ; i < nums. length; i++ ) {
if ( set. contains ( nums[ i] ) ) return nums[ i] ;
else {
set. add ( nums[ i] ) ;
}
}
return - 1 ;
}
}
方法2 :
public int findRepeatNumber ( int [ ] nums) {
Arrays. sort ( nums) ;
for ( int i = 0 ; i < nums. length- 1 ; i++ ) {
if ( nums[ i] == nums[ i+ 1 ] ) return nums[ i] ;
}
return - 1 ;
}
剑04.二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 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 。
采用二分查找
public class Solution {
public static boolean findNumberIn2DArray ( int [ ] [ ] matrix, int target) {
int n= matrix. length;
for ( int i = 0 ; i < n; i++ ) {
int left= 0 ;
int right= matrix[ i] . length- 1 ;
while ( left<= right) {
int mid= ( right- left) / 2 + left;
if ( matrix[ i] [ mid] > target) {
right= mid- 1 ;
} else if ( matrix[ i] [ mid] < target) {
left= mid+ 1 ;
} else {
return true ;
}
}
}
return false ;
}
}
剑05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20" 。
示例 1 :
输入:s = "We are happy."
输出:"We%20are%20happy."
public class Solution {
public String replaceSpace ( String s) {
StringBuilder sb = new StringBuilder ( ) ;
for ( int i = 0 ; i < s. length ( ) ; i++ ) {
if ( s. charAt ( i) == ' ' ) sb. append ( "%20" ) ;
else sb. append ( s. charAt ( i) ) ;
}
return sb. toString ( ) ;
}
}
剑06.从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1 :
输入:head = [ 1 , 3 , 2 ]
输出:[ 2 , 3 , 1 ]
栈思想
class Solution {
public int [ ] reversePrint ( ListNode head) {
if ( head== null) return new int [ ] { } ;
ListNode cur= head;
Stack< Integer> stack = new Stack < > ( ) ;
while ( cur!= null) {
stack. push ( cur. val) ;
cur= cur. next;
}
int [ ] res= new int [ stack. size ( ) ] ;
int count= 0 ;
for ( int i= 0 ; i< res. length; i++ ) {
res[ count++ ] = stack. pop ( ) ;
}
return res;
}
}
剑07.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
前序遍历 preorder = [ 3 , 9 , 20 , 15 , 7 ]
中序遍历 inorder = [ 9 , 3 , 15 , 20 , 7 ]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode ( int x) { val = x; }
}
public class Solution {
public TreeNode reConstructBinaryTree ( int [ ] pre, int [ ] in) {
if ( pre== null|| pre. length== 0 ) return null;
TreeNode root= new TreeNode ( pre[ 0 ] ) ;
int index= searchRoot ( pre, in) ;
root. left= reConstructBinaryTree ( Arrays. copyOfRange ( pre, 1 , index+ 1 ) ,
Arrays. copyOfRange ( in, 0 , index) ) ;
root. right= reConstructBinaryTree ( Arrays. copyOfRange ( pre, index+ 1 , in. length) ,
Arrays. copyOfRange ( in, index+ 1 , in. length) ) ;
return root;
}
public int searchRoot ( int [ ] pre, int [ ] in) {
for ( int i= 0 ; i< in. length; i++ ) {
if ( pre[ 0 ] == in[ i] ) return i;
}
return 0 ;
}
}
剑09. 用两个栈实现队列
* 用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,
* 分别完成在队列尾部插入整数和在队列头部删除整数的功能。( 若队列中没有元素,deleteHead 操作返回 - 1 )
* 示例 1 :
* 输入:
* [ "CQueue" , "appendTail" , "deleteHead" , "deleteHead" ]
* [ [ ] , [ 3 ] , [ ] , [ ] ]
* 输出:[ null, null, 3 , - 1 ]
public class Solution {
Stack< Integer> stack1;
Stack< Integer> stack2;
public Solution ( ) {
stack1 = new Stack < > ( ) ;
stack2 = new Stack < > ( ) ;
}
public void appendTail ( int value) {
stack1. push ( value) ;
}
public int deleteHead ( ) {
if ( stack2. isEmpty ( ) ) {
while ( ! stack1. isEmpty ( ) ) {
stack2. push ( stack1. pop ( ) ) ;
}
}
return stack2. isEmpty ( ) ? - 1 : stack2. pop ( ) ;
}
}
剑10.斐波拉契数列
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:
F ( 0 ) = 0 , F ( 1 ) = 1
F ( N) = F ( N - 1 ) + F ( N - 2 ) , 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9 + 7 (1000000007 ),如计算初始结果为:1000000008 ,请返回 1 。
示例 1 :
输入:n = 2
输出:1
class Solution {
public int fib ( int n) {
int dp[ ] = new int [ n+ 2 ] ;
dp[ 0 ] = 0 ;
dp[ 1 ] = 1 ;
for ( int i = 2 ; i <= n; i++ ) {
dp[ i] = dp[ i- 1 ] + dp[ i- 2 ] ;
dp[ i] %= 1000000007 ;
}
return dp[ n] ;
}
}
剑10.青蛙跳台阶
一只青蛙一次可以跳上1 级台阶,也可以跳上2 级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9 + 7 (1000000007 ),如计算初始结果为:1000000008 ,请返回 1 。
示例 1 :
输入:n = 2
输出:2
class Solution {
public int numWays ( int n) {
int dp[ ] = new int [ n+ 2 ] ;
if ( n== 0 ) { return 1 ; }
dp[ 1 ] = 1 ;
dp[ 2 ] = 2 ;
for ( int i = 3 ; i <= n ; i++ ) {
dp[ i] = dp[ i- 1 ] + dp[ i- 2 ] ;
dp[ i] %= 1000000007 ;
}
return dp[ n] ;
}
}
剑10. 变态跳台阶
public class Solution {
public int JumpFloorII ( int target) {
int [ ] dp = new int [ target+ 1 ] ;
for ( int i= 1 ; i<= target; i++ ) {
int sum = 0 ;
for ( int j= 1 ; j< i; j++ ) {
sum = sum + dp[ j] ;
}
dp[ i] = sum+ 1 ;
}
return dp[ target] ;
}
}
剑11. 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [ 3 , 4 , 5 , 1 , 2 ] 为 [ 1 , 2 , 3 , 4 , 5 ] 的一个旋转,该数组的最小值为1 。
输入:[ 3 , 4 , 5 , 1 , 2 ]
输出:1
class Solution {
public int minArray ( int [ ] numbers) {
MaoPao ( numbers) ;
return numbers[ 0 ] ;
}
public void MaoPao ( int [ ] numbers) {
for ( int i= 0 ; i< numbers. length; i++ ) {
for ( int j= 0 ; j< numbers. length- 1 - i; j++ ) {
if ( numbers[ j] > numbers[ j+ 1 ] ) {
int temp= numbers[ j+ 1 ] ;
numbers[ j+ 1 ] = numbers[ j] ;
numbers[ j] = temp;
}
}
}
}
}
剑12. 矩阵中的路径
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3 ×4 的矩阵中包含一条字符串“bfce”的路径(路径中的字母用加粗标出)。
[ [ "a" , "b" , "c" , "e" ] ,
[ "s" , "f" , "c" , "s" ] ,
[ "a" , "d" , "e" , "e" ] ]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
输入:board = [ [ "A" , "B" , "C" , "E" ] , [ "S" , "F" , "C" , "S" ] , [ "A" , "D" , "E" , "E" ] ] , word = "ABCCED"
输出:true
public class Solution {
public boolean hasPath ( char [ ] matrix, int rows, int cols, char [ ] str)
{
for ( int x = 0 ; x < rows; x++ ) {
for ( int y = 0 ; y < cols; y++ ) {
if ( dfs ( x, y, matrix, rows, cols, 0 , str, new boolean [ rows] [ cols] ) ) {
return true ;
}
}
}
return false ;
}
private boolean dfs ( int x, int y, char [ ] matrix, int rows, int cols, int k, char [ ] str, boolean [ ] [ ] booleans) {
if ( x< 0 || y< 0 || x> rows- 1 || y> cols- 1 ) return false ;
if ( booleans[ x] [ y] ) return false ;
if ( matrix[ cols* x+ y] != str[ k] ) return false ;
if ( k== str. length- 1 ) return true ;
booleans[ x] [ y] = true ;
boolean flag= dfs ( x- 1 , y, matrix, rows, cols, k+ 1 , str, booleans)
|| dfs ( x+ 1 , y, matrix, rows, cols, k+ 1 , str, booleans)
|| dfs ( x, y- 1 , matrix, rows, cols, k+ 1 , str, booleans)
|| dfs ( x, y+ 1 , matrix, rows, cols, k+ 1 , str, booleans) ;
if ( ! flag) {
booleans[ x] [ y] = false ;
}
return flag;
}
}
剑13. 机器人的运动范围
地上有一个m行n列的方格,从坐标 [ 0 , 0 ] 到坐标 [ m- 1 , n- 1 ] 。一个机器人从坐标 [ 0 , 0 ] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格
外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18 时,机
器人能够进入方格 [ 35 , 37 ] ,因为3 + 5 + 3 + 7 = 18 。但它不能进入方格 [ 35 , 38 ] ,
因为3 + 5 + 3 + 8 = 19 。请问该机器人能够到达多少个格子?
示例 1 :
输入:m = 2 , n = 3 , k = 1
输出:3
public class Solution {
public int movingCount ( int threshold, int rows, int cols)
{
for ( int x = 0 ; x < rows; x++ ) {
for ( int y = 0 ; y < cols; y++ ) {
return dfs ( x, y, threshold, rows, cols, new boolean [ rows] [ cols] ) ;
}
}
return 0 ;
}
private int dfs ( int x, int y, int threshold, int rows, int cols, boolean [ ] [ ] booleans) {
if ( x< 0 || y< 0 || x> rows- 1 || y> cols- 1 ) return 0 ;
if ( x/ 10 + x% 10 + y/ 10 + y% 10 > threshold) return 0 ;
if ( booleans[ x] [ y] ) return 0 ;
booleans[ x] [ y] = true ;
return dfs ( x- 1 , y, threshold, rows, cols, booleans)
+ dfs ( x+ 1 , y, threshold, rows, cols, booleans)
+ dfs ( x, y- 1 , threshold, rows, cols, booleans)
+ dfs ( x, y+ 1 , threshold, rows, cols, booleans) + 1 ;
}
}
剑14. 剪绳子
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n> 1 并且m> 1 ),每段绳子的长度记为 k[ 0 ] , k[ 1 ] . . . k[ m - 1 ] 。请问 k[ 0 ] * k[ 1 ] * . . . *k[ m - 1 ] 可能的最大乘积是多少?例如,当绳子的长度是8 时,我们把它剪成长度分别为2 、3 、3 的三段,此时得到的最大乘积是18 。
答案需要取模 1e9 + 7 (1000000007 ),如计算初始结果为:1000000008 ,请返回 1
输入: 2
输出: 1
解释: 2 = 1 + 1 , 1 × 1 = 1
public class Solution {
public int cutRope ( int target) {
if ( target<= 3 ) return target- 1 ;
int a= target/ 3 ;
int b= target% 3 ;
if ( b== 0 ) return ( int ) Math. pow ( 3 , a) ;
else if ( b== 1 ) return ( int ) ( 4 * Math. pow ( 3 , ( a- 1 ) ) ) ;
else return ( int ) ( 2 * Math. pow ( 3 , a) ) ;
}
}
剑15. 二进制中1的个数
public class Solution {
public static void main ( String[ ] args) {
}
public int NumberOf1 ( int n) {
int res= 0 ;
while ( n!= 0 ) {
res+= n& 1 ;
n>>>= 1 ;
}
return res;
}
}
剑16. 数值的整数次方
实现函数double Power ( double base, int exponent) ,求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。
示例 1 :
输入: 2.00000 , 10
输出: 1024.00000
class Solution {
public double myPow ( double x, int n) {
long N= n;
if ( N < 0 ) {
return 1 / Pow ( x, ( - N) ) ;
} else {
return Pow ( x, N) ;
}
}
private double Pow ( double x, long n) {
if ( n== 0 ) return 1 ;
if ( x== 1 ) return 1 ;
if ( n% 2 == 0 ) {
double start= Pow ( x, n/ 2 ) ;
return start* start;
} else {
double start= Pow ( x, ( n- 1 ) / 2 ) ;
return start* start* x;
}
}
}
剑17. 打印1到最大的n位数
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3 ,则打印出 1 、2 、3 一直到最大的 3 位数 999 。
示例 1 :
输入: n = 1
输出: [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
class Solution {
public int [ ] printNumbers ( int n) {
int length= ( int ) Math. pow ( 10 , n) - 1 ;
int [ ] res= new int [ length] ;
for ( int i= 0 ; i< length; i++ ) {
res[ i] = i+ 1 ;
}
return res;
}
}
剑18. 删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
示例 1 :
输入: head = [ 4 , 5 , 1 , 9 ] , val = 5
输出: [ 4 , 1 , 9 ]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 - > 1 - > 9.
public class Solution {
public ListNode deleteNode ( ListNode head, int val) {
if ( head== null) return null;
ListNode dummy= new ListNode ( 0 ) ;
ListNode cur= dummy;
dummy. next= head;
while ( cur. next!= null) {
if ( cur. next. val== val) {
cur. next= cur. next. next;
break ;
}
cur= cur. next;
}
return dummy. next;
}
}
剑18. 删除链表的重复节点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,
* 重复的结点不保留,返回链表头指针。
* 例如,链表1 - > 2 - > 3 - > 3 - > 4 - > 4 - > 5 处理后为 1 - > 2 - > 5
* 思路:先找头指针不重复的点,之后找剩余的点* /
public class Solution2 {
public ListNode deleteDuplication ( ListNode pHead) {
ListNode dummy = new ListNode ( 0 ) ;
ListNode pre= dummy;
ListNode cur= pHead;
dummy. next= pHead;
while ( cur!= null&& cur. next!= null) {
if ( cur. val== cur. next. val) {
int temp= cur. val;
while ( cur!= null&& temp== cur. val) {
cur= cur. next;
}
pre. next= cur;
} else {
pre= cur;
cur= cur. next;
}
}
return dummy. next;
}
}
剑20. 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100" 、"5e2" 、"-123" 、"3.1416" 、"-1E-16" 、"0123" 都表示数值,但"12e" 、"1a3.14" 、"1.2.3" 、"+-5" 及"12e+5.4" 都不是。
class Solution {
public boolean isNumber ( String s) {
if ( s. endsWith ( "F" ) || s. endsWith ( "f" ) || s. endsWith ( "D" ) || s. endsWith ( "d" ) ) {
return false ;
}
try {
double d= Double. parseDouble ( s) ;
} catch ( NumberFormatException e) {
return false ;
}
return true ;
}
}
剑21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
示例:
输入:nums = [ 1 , 2 , 3 , 4 ]
输出:[ 1 , 3 , 2 , 4 ]
注:[ 3 , 1 , 2 , 4 ] 也是正确的答案之一。
public class Solution {
public int [ ] exchange ( int [ ] nums) {
int left= 0 , right= nums. length- 1 ;
int temp;
while ( left< right) {
while ( left< right && nums[ left] % 2 == 1 ) left++ ;
while ( left< right && nums[ right] % 2 == 0 ) right-- ;
temp= nums[ left] ;
nums[ left] = nums[ right] ;
nums[ right] = temp;
}
return nums;
}
}
剑22. 链表中的倒数第K个结点
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1 开始计数,即链表的尾节点是倒数第1 个节点。例如,一个链表有6 个节点,从头节点开始,它们的值依次是1 、2 、3 、4 、5 、6 。这个链表的倒数第3 个节点是值为4 的节点。
public class Solution {
public ListNode getKthFromEnd ( ListNode head, int k) {
ListNode fast= head;
ListNode slow= head;
for ( int i = 0 ; i < k; i++ ) {
fast= fast. next;
}
while ( fast!= null) {
fast= fast. next;
slow= slow. next;
}
return slow;
}
}
剑23. 反转链表
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1 - > 2 - > 3 - > 4 - > 5 - > NULL
输出: 5 - > 4 - > 3 - > 2 - > 1 - > NULL
class Solution {
public ListNode reverseList ( ListNode head) {
ListNode prev= null;
ListNode cur= head;
ListNode temp= null;
while ( cur!= null) {
temp= cur. next;
cur. next= prev;
prev= cur;
cur= temp;
}
return prev;
}
}
剑23. 反转链表2
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1 - > 2 - > 3 - > 4 - > 5 - > NULL, m = 2 , n = 4
输出: 1 - > 4 - > 3 - > 2 - > 5 - > NULL
public class Solution {
public ListNode reverseBetween ( ListNode head, int m, int n) {
ListNode dumpy = new ListNode ( 0 ) ;
dumpy. next= head;
ListNode P1= dumpy;
ListNode P2= head;
for ( int i= 1 ; i< m; i++ ) {
P1= P1. next;
P2= P2. next;
}
for ( int i = 0 ; i < n - m; i++ ) {
ListNode cur= P2. next;
P2. next= cur. next;
cur. next= P1. next;
P1. next= cur;
}
return dumpy. next;
}
}
剑25. 合并两个排序链表
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
输入:1 - > 2 - > 4 , 1 - > 3 - > 4
输出:1 - > 1 - > 2 - > 3 - > 4 - > 4
public class Solution {
public ListNode Merge ( ListNode list1, ListNode list2) {
ListNode dump= new ListNode ( 0 ) ;
ListNode cur= dump;
while ( list1!= null&& list2!= null) {
if ( list1. val< list2. val) {
cur. next= new ListNode ( list1. val) ;
list1= list1. next;
} else {
cur. next= new ListNode ( list2. val) ;
list2= list2. next;
}
cur= cur. next;
}
if ( list1!= null) {
cur. next= list1;
} else {
cur. next= list2;
}
return dump. next;
}
}
剑26. 树的子结构
输入两棵二叉树A和B,判断B是不是A的子结构。( 约定空树不是任意一个树的子结构) B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:
给定的树 A:
3
/ \
4 5
/ \
1 2
给定的树 B:
4
/
1
返回 true ,因为 B 与 A 的一个子树拥有相同的结构和节点值。
示例 1 :
输入:A = [ 1 , 2 , 3 ] , B = [ 3 , 1 ]
输出:false
class Solution {
public boolean isSubStructure ( TreeNode A, TreeNode B) {
if ( A== null|| B== null) return false ;
return helper ( A, B) || isSubStructure ( A. left, B) || isSubStructure ( A. right, B) ;
}
private boolean helper ( TreeNode rootA, TreeNode rootB) {
if ( rootB== null) return true ;
if ( rootA== null) return false ;
return rootA. val== rootB. val&& helper ( rootA. left, rootB. left) && helper ( rootA. right, rootB. right) ;
}
}
剑27. 二叉树的镜像
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
4
/ \
2 7
/ \ / \
1 3 6 9
镜像输出:
4
/ \
7 2
/ \ / \
9 6 3 1
输入:root = [ 4 , 2 , 7 , 1 , 3 , 6 , 9 ]
输出:[ 4 , 7 , 2 , 9 , 6 , 3 , 1 ]
class Solution {
public TreeNode mirrorTree ( TreeNode root) {
helper ( root) ;
return root;
}
public void helper ( TreeNode root) {
if ( root== null) return ;
TreeNode temp= root. left;
root. left= root. right;
root. right= temp;
helper ( root. left) ;
helper ( root. right) ;
}
}
剑28. 对称的二叉树
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [ 1 , 2 , 2 , 3 , 4 , 4 , 3 ] 是对称的。
1
/ \
2 2
/ \ / \
3 4 4 3
但是下面这个 [ 1 , 2 , 2 , null, 3 , null, 3 ] 则不是镜像对称的:
1
/ \
2 2
\ \
3 3
输入:root = [ 1 , 2 , 2 , 3 , 4 , 4 , 3 ]
输出:true
class Solution {
public boolean isSymmetric ( TreeNode root) {
if ( root== null) return true ;
return helper ( root. left, root. right) ;
}
private boolean helper ( TreeNode root1, TreeNode root2) {
if ( root1== null&& root2== null) return true ;
if ( root1== null|| root2== null) return false ;
return ( root1. val== root2. val) && helper ( root1. left, root2. right)
&& helper ( root1. right, root2. left) ;
}
}
剑29. 顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1 :
输入:matrix = [ [ 1 , 2 , 3 ] , [ 4 , 5 , 6 ] , [ 7 , 8 , 9 ] ]
输出:[ 1 , 2 , 3 , 6 , 9 , 8 , 7 , 4 , 5 ]
示例 2 :
输入:matrix = [ [ 1 , 2 , 3 , 4 ] , [ 5 , 6 , 7 , 8 ] , [ 9 , 10 , 11 , 12 ] ]
输出:[ 1 , 2 , 3 , 4 , 8 , 12 , 11 , 10 , 9 , 5 , 6 , 7 ]
1. 空值处理: 当 matrix 为空时,直接返回空列表 [ ] 即可。
* 2. 初始化: 矩阵 左、右、上、下 四个边界 l , r , t , b ,用于打印的结果列表 res 。
* 3. 循环打印: “从左向右、从上向下、从右向左、从下向上” 四个方向循环,每个方向打印中做以下三件事 (各方向的具体信息见下表) ;
* -- ( 1 ) 根据边界打印,即将元素按顺序添加至列表 res 尾部;
* -- ( 2 ) 边界向内收缩 l(代表已被打印);
* -- ( 3 ) 判断是否打印完毕(边界是否相遇),若打印完毕则跳出
class Solution {
public int [ ] spiralOrder ( int [ ] [ ] matrix) {
if ( matrix== null|| matrix. length== 0 ) return new int [ ] { } ;
int left= 0 , right= matrix[ 0 ] . length- 1 ;
int top= 0 , bellow= matrix. length- 1 ;
int count= 0 ;
int res[ ] = new int [ ( bellow+ 1 ) * ( right+ 1 ) ] ;
while ( true ) {
for ( int i = left; i <= right; i++ ) {
res[ count++ ] = matrix[ top] [ i] ;
}
if ( ++ top> bellow) break ;
for ( int i = top; i <= bellow; i++ ) {
res[ count++ ] = matrix[ i] [ right] ;
}
if ( left> -- right) break ;
for ( int i = right; i >= left; i-- ) {
res[ count++ ] = matrix[ bellow] [ i] ;
}
if ( top> -- bellow) break ;
for ( int i = bellow; i >= top; i-- ) {
res[ count++ ] = matrix[ i] [ left] ;
}
if ( ++ left> right) break ;
}
return res;
}
}
剑30. 包含main函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O ( 1 ) 。
实例:
MinStack minStack = new MinStack ( ) ;
minStack. push ( - 2 ) ;
minStack. push ( 0 ) ;
minStack. push ( - 3 ) ;
minStack. min ( ) ; -- > 返回 - 3.
minStack. pop ( ) ;
minStack. top ( ) ; -- > 返回 0.
minStack. min ( ) ; -- > 返回 - 2.
class MinStack {
Stack< Integer> stack= new Stack < Integer> ( ) ;
public MinStack ( ) {
}
public void push ( int x) {
stack. push ( x) ;
}
public void pop ( ) {
if ( ! stack. isEmpty ( ) ) {
stack. pop ( ) ;
}
}
public int top ( ) {
int peak= 0 ;
if ( ! stack. isEmpty ( ) ) {
peak= stack. peek ( ) ;
}
return peak;
}
public int min ( ) {
int min= top ( ) ;
if ( ! stack. isEmpty ( ) ) {
Iterator< Integer> iterator = stack. iterator ( ) ;
while ( iterator. hasNext ( ) ) {
int temp= iterator. next ( ) ;
if ( min> temp) {
min= temp;
}
}
}
return min;
}
}
剑31. 栈的压入弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 { 1 , 2 , 3 , 4 , 5 } 是某栈的压栈序列,序列 { 4 , 5 , 3 , 2 , 1 } 是该压栈序列对应的一个弹出序列,但 { 4 , 3 , 5 , 1 , 2 } 就不可能是该压栈序列的弹出序列。
示例 1 :
输入:pushed = [ 1 , 2 , 3 , 4 , 5 ] , popped = [ 4 , 5 , 3 , 2 , 1 ]
输出:true
解释:我们可以按以下顺序执行:
push ( 1 ) , push ( 2 ) , push ( 3 ) , push ( 4 ) , pop ( ) - > 4 ,
push ( 5 ) , pop ( ) - > 5 , pop ( ) - > 3 , pop ( ) - > 2 , pop ( ) - > 1
public class Solution {
public boolean validateStackSequences ( int [ ] pushed, int [ ] popped) {
Stack< Integer> stack = new Stack < > ( ) ;
int i= 0 ;
for ( int num: pushed) {
stack. push ( num) ;
while ( ! stack. isEmpty ( ) && stack. peek ( ) == popped[ i] ) {
stack. pop ( ) ;
i++ ;
}
}
return stack. isEmpty ( ) ;
}
}