1在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
两种思路:
一种是:把每一行看成有序递增的数组,利用二分查找,通过遍历每一行得到答案,时间复杂度是nlogn
public class Solution {
public boolean Find(int [][]array,int target) {
for(inti=0;i<array.length;i++){
intlow=0;
inthigh=array[i].length-1;
while(low<=high){
intmid=(low+high)/2;
if(target>array[i][mid])
low=mid+1;
elseif(target<array[i][mid])
high=mid-1;
else
returntrue;
}
}
returnfalse;
}
}
另外一种思路是:
利用二维数组由上到下,由左到右递增的规律,
那么选取右上角或者左下角的元素a[row][col]与target进行比较,
当target小于元素a[row][col]时,那么target必定在元素a所在行的左边,
即col--;
当target大于元素a[row][col]时,那么target必定在元素a所在列的下边,
即row++;
public class Solution {
public boolean Find(int [][]array,int target) {
introw=0;
intcol=array[0].length-1;
while(row<=array.length-1&&col>=0){
if(target==array[row][col])
returntrue;
elseif(target>array[row][col])
row++;
else
col--;
}
returnfalse;
}
}
7题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。队列中的元素为int类型。
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = newStack<Integer>();
Stack<Integer> stack2 = newStack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack1.empty()&&stack2.empty()){
thrownew RuntimeException("Queue is empty!");
}
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.pop());
}
}
returnstack2.pop();
}
}
8[编程题]斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
n<=39
下例是一个简单的动态规划,以一定的空间代价避免代价更大的重复计算的栈空间浪费:
public classSolution {
public int Fibonacci(int n) {
if (n <= 1) {
return n;
}
int[] dp = new int[n + 1];
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
public classSolution {
public int JumpFloor(int target) {
if (target <= 2){
return target;
}
int[] dp = new int[target + 1];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= target; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[target];
}
}
二进制中1的个数
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
链接:https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8
来源:牛客网
public
class
Solution {
//
从n的2进制形式的最右边开始判断是不是1
/*
*
该解法如果输入时负数会陷入死循环,
*
因为负数右移时,在最高位补得是1
*
二本题最终目的是求1的个数,那么会有无数个
* 1
了。
*/
//-------------
可能陷入死循环的解法---------------------
publicstatic int NumberOf1_CanNotUse(int n) {
int count = 0;
while (n != 0) {
/*
*
用1和n进行位与运算,
*
结果要是为1则n的2进制形式
*
最右边那位肯定是1,否则为0
*/
if
((n & 1) ==1) {
count++;
}
//
把n的2进制形式往右推一位
n = n >> 1;
}
return
count;
}
//---------------
正解--------------------------------
//
思想:用1(1自身左移运算,其实后来就不是1了)和n的每位进行位与,来判断1的个数
private
static
int
NumberOf1_low(int
n){
int
count = 0;
int
flag = 1;
while
(flag != 0) {
if
((n & flag)!= 0) {
count++;
}
flag = flag << 1;
}
return
count;
}
//--------------------
最优解----------------------------
public
static
int
NumberOf1(int
n){
int
count = 0;
while
(n != 0) {
++count;
n = (n - 1) & n;
}
return
count;
}
public
static
void
main(String[] args) {
//
使用n=10,二进制形式为1010,则1的个数为2;
int
n = -10;
System.out.println(n + "
的二进制中1的个数:"
+ NumberOf1(n));
}
}
11题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
|
[编程题]调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
|
时间复杂度为O(n),空间复杂度为O(n)的算法
/*
整体思路:
首先统计奇数的个数
然后新建一个等长数组,设置两个指针,奇数指针从0开始,偶数指针从奇数个数的末尾开始 遍历,填数
*/
public
class
Solution {
public
void
reOrderArray(int
[] array) {
if(array.length==0||array.length==1)return;
int
oddCount=0,oddBegin=0;
int[]newArray=new
int[array.length];
for(int
i=0;i<array.length;i++){
if((array[i]&1)==1)oddCount++;
}
for(int
i=0;i<array.length;i++){
if((array[i]&1)==1)newArray[oddBegin++]=array[i];
else
newArray[oddCount++]=array[i];
}
for(int
i=0;i<array.length;i++){
array[i]=newArray[i];
}
}
}
首先想到的就是类似于插入排序,而且我感觉插入排序还是比较好的,毕竟不用借助其他的数据结构,
所以空间复杂度为O(1),时间复杂度为O(N^2)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
插排思想
public
class
Solution {
public
void
reOrderArray(int
[] array) {
int
num = 0;
for
(int
i = 0; i <array.length; i++) {
if
(array[i]%2!=0) {
if
(num!=i) {
int
temp = array[num];
array[num]= array[i];
for
(int
j = i; j >num+1; j--) {
array[j]= array[j-1];
}
array[num+1]= temp;
}
num++;
}
}
}
}
[编程题]反转链表
输入一个链表,反转链表后,输出链表的所有元素。
Java 循环操作 详细思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
18树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
/*
思路:参考剑指offer
1
、首先设置标志位result = false,因为一旦匹配成功result就设为true,
剩下的代码不会执行,如果匹配不成功,默认返回false
2
、递归思想,如果根节点相同则递归调用DoesTree1HaveTree2(),
如果根节点不相同,则判断tree1的左子树和tree2是否相同,
再判断右子树和tree2是否相同
3
、注意null的条件,HasSubTree中,如果两棵树都不为空才进行判断,
DoesTree1HasTree2
中,如果Tree2为空,则说明第二棵树遍历完了,即匹配成功,
tree1
为空有两种情况(1)如果tree1为空&&tree2不为空说明不匹配,
(2)如果tree1为空,tree2为空,说明匹配。
*/
public
class
Solution {
public
boolean
HasSubtree(TreeNoderoot1,TreeNode root2) {
boolean
result = false;
if(root1!= null
&& root2 != null){
if(root1.val== root2.val){
result= DoesTree1HaveTree2(root1,root2);
}
if(!result){result= HasSubtree(root1.left, root2);}
if(!result){result= HasSubtree(root1.right, root2);}
}
return
result;
}
public
boolean
DoesTree1HaveTree2(TreeNoderoot1,TreeNode root2){
if(root1== null
&& root2 != null) return
false;
if(root2== null) return
true;
if(root1.val!= root2.val) return
false;
return
DoesTree1HaveTree2(root1.left, root2.left) &&DoesTree1HaveTree2(root1.right, root2.right);
}
}
二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
/*
先前序遍历这棵树的每个结点,如果遍历到的结点有子结点,就交换它的两个子节点,
当交换完所有的非叶子结点的左右子结点之后,就得到了树的镜像 */
/**
public
class
Solution {
public
void
Mirror(TreeNoderoot) {
if(root== null)
return;
if(root.left== null
&& root.right == null)
return;
TreeNodepTemp = root.left;
root.left= root.right;
root.right= pTemp;
if(root.left!= null)
Mirror(root.left);
if(root.right!= null)
Mirror(root.right);
}
}
二、用栈实现
import
java.util.Stack;
public
class
Solution {
public
void
Mirror(TreeNoderoot) {
if(root== null){
return;
}
Stack<TreeNode>stack = new
Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNodenode = stack.pop();
if(node.left!= null||node.right != null){
TreeNodetemp = node.left;
node.left= node.right;
node.right= temp;
}
if(node.left!=null){
stack.push(node.left);
}
if(node.right!=null){
stack.push(node.right);
}
}
}
}
[编程题]顺时针打印矩阵
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
importjava.util.ArrayList;
importjava.util.List;
public classSolution {
public ArrayList<Integer> printMatrix(int[][] matrix) {
ArrayList<Integer> res = newArrayList<Integer>();
if (matrix.length == 0) {
return res;
}
int rowBegin = 0;
int rowEnd = matrix.length-1;
int colBegin = 0;
int colEnd = matrix[0].length - 1;
while (rowBegin <= rowEnd &&colBegin <= colEnd) {
// Traverse Right
for (int j = colBegin; j <=colEnd; j ++) {
res.add(matrix[rowBegin][j]);
}
rowBegin++;
// Traverse Down
for (int j = rowBegin; j <=rowEnd; j ++) {
res.add(matrix[j][colEnd]);
}
colEnd--;
if (rowBegin <= rowEnd) {//
假如开始数组是[2,3],如果没有if,走完一圈是【2,3,2】,多了一个元素2.所以要加入判断
// Traverse Left
for (int j = colEnd; j >=colBegin; j --) {
res.add(matrix[rowEnd][j]);
}
}
rowEnd--;
if (colBegin <= colEnd) {
// Traver Up
for (int j = rowEnd; j >=rowBegin; j --) {
res.add(matrix[j][colBegin]);
}
}
colBegin ++;
}
return res;
}
}
[编程题]包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
|
解题思路:
我们可以设计两个栈:StackDate和StackMin,一个就是普通的栈,另外一个存储push进来的最小值。
首先是push操作:
每次压入的数据newNum都push进StackDate中,然后判断StackMin是否为空,如果为空那也把newNum同步压入 StackMin里;如果不为空,就先比较newNum和StackMin中栈顶元素的大小,如果newNum较大,那就不压入StackMin里,否则 就同步压入StackMin里。如:
接着是pop操作
先将StackDate中取出的数据value与StackMin的栈顶元素比较,因为对应push操作,value不可能小于StackMin中的栈顶元素,最多是相等。如果相等,那么StackMin中也取出数据,同时返回value,否则只是返回value就可以了。
最后是getMin操作
1 |
|
|
【思路】借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
模拟堆栈操作:将原数列依次压栈,栈顶元素与所给出栈队列相比,如果相同则出栈,
如果不同则继续压栈,直到原数列中所有数字压栈完毕。
检测栈中是否为空,若空,说明出栈队列可由原数列进行栈操作得到。否则,说明出栈队列不能由原数列进行栈操作得到。
举例:
入栈1,2,3,4,5
出栈4,5,3,2,1
首先1入辅助栈,此时栈顶1≠4,继续入栈2
此时栈顶2≠4,继续入栈3
此时栈顶3≠4,继续入栈4
此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3
此时栈顶3≠5,继续入栈5
此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3
….
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
从上往下打印二叉树
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
借助队列:
public classSolution {
publicArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer>list = new ArrayList<Integer>();
if(root==null){
returnlist;
}
Queue<TreeNode>queue = new LinkedList<TreeNode>();
queue.offer(root);
while(!queue.isEmpty()) {
TreeNodetreeNode = queue.poll();
if(treeNode.left != null) {
queue.offer(treeNode.left);
}
if(treeNode.right != null) {
queue.offer(treeNode.right);
}
list.add(treeNode.val);
}
returnlist;
}
}
二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
链接:https://www.nowcoder.com/questionTerminal/a861533d45854474ac791d90e447bafd
二叉树中和为某一值的路径
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径
链接:https://www.nowcoder.com/questionTerminal/b736e784e3e34731af99065031301bca
|
链接:https://www.nowcoder.com/questionTerminal/b736e784e3e34731af99065031301bca
来源:牛客网
public
ArrayList<ArrayList<Integer>>FindPath(TreeNoderoot,int
target){
ArrayList<ArrayList<Integer>>result=new
ArrayList<>();
if(null==root){
return
result;
}
ArrayList<Integer>nodeValList=new
ArrayList<>();
return
findPathHelper(result,nodeValList,root,target);
}
private
ArrayList<ArrayList<Integer>>findPathHelper(ArrayList<ArrayList<Integer>>result,List<Integer>nodeValList,TreeNoderoot,int
target){
if(null==root){
return
result;
}
nodeValList.add(root.val);
target-=root.val;
if(target==0&&root.left==null&&root.right==null){
result.add(new
ArrayList<>(nodeValList));
}else{
findPathHelper(result,nodeValList,root.left,target);
findPathHelper(result,nodeValList,root.right,target);
}
nodeValList.remove(nodeValList.size()-1);
return
result;
}