1.二维数组中的查找:
二维数组,每行都从左往右递增,每列都从上往下递增。现在该数组中查找是否有指定的数。
解析:首先想到递归思想、二分查找思想。接着,由于左上角或右下角的数据类似于二分查找的中位数,故可以以此为切入点,不断切割二维数组,最终得到查找结果。
2.替换空格:
实现一个函数,将一个字符串中的每个空格替换成“%20”。
解析:1.replaceAll(" ","%20")。
2.StringBuilder();
3.从尾到头打印链表:
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
解析:1.stack() stack.push() stack.pop();
4.重建二叉树:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
解析:可以通过前序遍历的结果,将二叉树分成左右子树,进而使用递归思想,返回根节点的左右节点。
5.用两个栈实现队列:
用两个栈来实现一个队列,完成队列的Push和Pop操作。队列中的元素为int类型。
解析:push()时只操作第一个栈,pop时把第一个栈元素压入第二个栈,删除后在把元素还回第一个栈。
6.旋转数组的最小数字:
输入一个非减排序数组的一个旋转,输出该旋转数组的最小元素。
解析:找断点,最小的数字为该断点。
7.斐波那契数列:
输出斐波那契数列的第n项。
解析:递归,F(n)=F(n-1)+F(n-2)
8.跳台阶:
一只青蛙一次可以跳1级台阶,也可以跳2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法。
解析:斐波那契数列原型。
9.变态跳台阶:
一只青蛙一次可以跳上1级台阶,也可以跳上2级......它也可以跳上n级。求该青蛙可以跳上一个n级台阶总共有多少种跳法。
解析:F(n)=F(n-1)+F(n-2)+...+F(1)
10.矩形覆盖:
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
解析:递归,F(n)=F(n-1)+F(n-2)
11.二进制中1的个数:
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
解析:按位与操作,n&(n-1)能够消除二进制n中最右边的1,while循环直到结果为0。
12.数值的整数次方:
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
解析:方法一 递归 ,F(n) =F(n/2)*F(n/2)。注意return条件,n为奇数{1.n>0,F(n) =F(n/2)*F(n/2)*base,
2.n<0,F(n) =F(n/2)*F(n/2)/base}
方法二:二进制的与操作与移位操作。10^13。将13用二进制表示为1101。则10^13=10^1000*10^0100*10^0001。
while(exponent!=0) 。。。。。。。。 13>>=1。
13.调整数组顺序使奇数位于偶数前面:
使得所有奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和偶数的位置不变。
解析:双指针,一个指向当前排序奇数的数组位置,一个指向偶数所到的位置,一次遍历,当两指针重合结束,还存在偶数顺序完全倒序的问题,需要将右边偶数转变顺序。
14.链表中倒数第k个节点:
输入一个链表,输出该链表中倒数第k个结点。
解析:设立两个节点来遍历,第二个节点与第一个节点间隔k
27.字符串的排列:
输入一个字符串,按字典序打印出该字符串中字符的所有排列
解析:1.先对字符串中的字符进行排序。2.递归不断减少字符串的个数。
28.数组中出现次数超过一半的数字
有一个数字超过一半,请找出这个数字,如果不存在输出0
解析:一个指针,一次遍历,遇到不同数字减一,遇到相同数字加一,当计数器为0就换指针指的下个数重新计数。
29.最小的K个数
输入n个整数,找出其中最小的K个数。
解析:排序
30.连续子数组的最大和
如果向量中包含负数,是否应该包含某个负数,例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8.
解析:不断累加,不断更新cmp值,小于0则重新开始,因为小于0的子向量对后面的序列毫无益处。
31.整数中1出现的次数
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?
解析:数学问题,找出规律,以个位为一个台阶、十位为一个台阶、百位为一个台阶、千位为一个台阶。
32.把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
解析:每两个数进行比较,写一个比较函数,比较函数为两个数从高位开始比较,数大的排在后面,如果相等,移一位继续比较,如果一个数没了位数,把最后一位和第二个数的移位比较。对数组进行重新排序,然后组合。
33.丑数
把只包含质因子2、3和5的数称作丑数。例如6、8都是丑数,但14不是,因为它包含质因子7。习惯上我们把1当作是第一个丑数。求按从小到大的顺序的第N个丑数。
解析:维护2、3、5的三个队列。变种为三个指针,一开始都指向1,分别乘以2、3、5,2最小,维护2的指针+1,指向2,继续将三个指针指向数乘以2、3、5进行比较移位。
34.第一个只出现一次的字符
在一个字符串中找到第一个只出现一次的字符,并返回它的位置,如果没有则返回-1。
解析:维护一个256的int型数组,数组的下标对应字符的ascii码,一次遍历str后查找数组中最小的坐标。
35.数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
36.两个链表的第一个公共节点
输入两个链表,找出它们的第一个公共节点。
解析:有公共节点的话,公共节点之后的节点全部相同。遍历完成之后回溯。可以用两个栈实现
37.数字在排序数组中出现的次数
统计一个数字在排序数组中出现的次数。
解析:二分?找到一个点,然后向两边扩展。
38.二叉数的深度
输入一颗二叉树,求该树的深度。从根节点到叶结点依次经过的节点形成树的一条路径,最长路径的长度为树的深度。
解析:深度优先遍历。
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
import java.util.ArrayList;
public class Solution {
public int TreeDepth(TreeNode root) {
if(root==null)
return 0;
ArrayList<Integer> path = new ArrayList<>();
/*int count =0;*/
helpDepth(root,path,1);
int result =0;
for(Integer i:path){
if(i>result)
result =i;
}
return result;
}
public void helpDepth(TreeNode root,ArrayList<Integer> path,int count){
if(root==null)
return;
if(root.left==null&&root.right==null){
path.add(count);
return;
}
helpDepth(root.left, path, count+1);
helpDepth(root.right, path, count+1);
}
}
39.平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树
解析:1..树的深度用深度优先遍历出所有路径长度,然后判断所有长度的最小值和最大值是否差值大于1。
40.数组中只出现一次的数字
一个整形数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。(考察异或逻辑)
解析:数组中的所有数字进行异或运算,结果等于两个只出现一次的数字异或的结果,找出这个结果中左边二进制第一个1的位置,然后将该数与数组进行&操作,形成两个子数组。
import java.util.ArrayList;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int cmp = array[0];
for(int i=1;i<array.length;i++){
cmp = cmp^array[i];
}
int two =cmp;
int one=0;
int j =1;
while(one==0){
one =j&two;
j=j*2;
}
j=j/2;
ArrayList<Integer> arr1 = new ArrayList<>();
ArrayList<Integer> arr2 = new ArrayList<>();
for(int k=0;k<array.length;k++){
if((array[k]&j)==0){
arr1.add(array[k]);
}else
arr2.add(array[k]);
}
num1[0]=arr1.get(0);
for(int p=1;p<arr1.size();p++){
num1[0]=num1[0]^arr1.get(p);
}
num2[0]=arr2.get(0);
for(int q=1;q<arr2.size();q++){
num2[0]=num2[0]^arr2.get(q);
}
}
}
41.和为S的连续正数序列
找出所有和为S的连续正数序列?
解析:维护两个指针,一个指向左边界,一个指向右边界,不断右移该滑动窗口。
42.和为S的两个数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
解析:两个指针,一个指向头,一个指向尾部,找到两个数。
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
int lo =0;
int hi =array.length-1;
ArrayList<Integer> res = new ArrayList<>();
if(hi==-1)
return res;
while(lo!=hi){
if(sum>array[lo]+array[hi]){
lo++;
}else if(sum<array[lo]+array[hi]){
hi--;
}else{
res.add(array[lo]);
res.add(array[hi]);
break;
}
}
return res;
}
}
43.左旋转字符串
解析:没难度。
44.翻转单词顺序列
解析: str.trim()
45.扑克牌顺子
解析:排序 然后看他们之间的间隔数是否小于0(大小王)的个数。
46.孩子们的游戏(圆圈中最后剩下的数)
解析:两种方法:1.维护一个链表,每个节点包含index和boolean,标志是否访问过。2.维护一个boolean数组,循环K次。
47.求1+2+3+...+n
要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句。
解析:递归
48.不用加减乘除做加法
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
解析:二进制运算。&算进位,^算不带进位的加法。
public class Solution {
public int Add(int num1,int num2) {
int with = num1&num2;
with<<=1;
int or = num1^num2;
while(with!=0){
int temp1 = or^with;
with = or&with;
with<<=1;
or = temp1;
}
return or;
}
}
49.把字符串转换成整数
解析: '9'-'0'=9;字符的比较。
50.数组中重复的数字
解析:维护一个长度相同n的数组,一次遍历原数组记录所有数出现的次数,再遍历该维护的数组。
51.构建乘积数组
给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。
解析:上下三角,对角线不算。
52.正则表达式匹配
解析:KMP算法
import java.util.regex.Pattern;
public class Solution {
//状态机
public boolean match(char[] str, char[] pattern)
{
String str1 = new String(str);
String patter = new String(pattern);
boolean res= Pattern.matches(patter,str1);
return res;
}
}
53.表示数值的字符串
实现一个函数用来判断字符串是否表示数值。
解析:正则表达式:str.matches(" "); string.matches("[\\+\\-]?\\d*(\\.\\d+)?([eE][\\+\\-]?\\d+)?");
54.字符流中第一个不重复的字符
解析:维护一个256的int数组,存它的坐标。
55.链表中环的入口节点
给一个链表,若其中包含环,请找出该链表的环的入口节点,否则,输出null。
解析:第一个相同的节点。==比较对象,equals比较内容。
56.删除链表中重复的节点
在一个排序的链表中,存在重复的节点,删除重复的节点,返回链表头指针。
解析:从左往右遍历,维护一个count指针,遇到重复的数+1,不同数清零。
57.二叉树的下一个结点
解析:考察中序遍历。
58.对称的二叉树
请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
解析:递归实现,左序左节点==右序右节点。有点精妙!!!!!因为其实每次递归,递归调用的函数形参都是关于二叉树对称的。
public class Solution {
boolean isSymmetrical(TreeNode pRoot)
{
if(pRoot==null)
return true;
return helpDefine(pRoot.left,pRoot.right);
}
public boolean helpDefine(TreeNode left,TreeNode right)
{
if(left==null&&right==null)
return true;
if(left==null)
return false;
if(right==null)
return false;
return helpDefine(left.left,right.right)&&helpDefine(left.right,right.left);
}
}
59.按之字形顺序打印二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
解析:层序遍历。可以维护两个栈来实现。
60.把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
解析:层序遍历。
61.序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树。
解析:前序遍历,将其转化为string输出并解析成为二叉树。如何反序列化二叉树结果?
public class Solution {
String Serialize(TreeNode root) {
StringBuilder builder = new StringBuilder<>();
helpSerialize(root,builder);
return builder.toString();
}
public void helpSerialize(root,builder){
if(root==null){
builder.add("#,");
return ;
}
builder.add(root.val+",");
helpSerialize(root.left,builder);
helpSerialize(root.right,builder);
}
TreeNode Deserialize(String str) {
char []arr = str.split(",");
}
}
62.二叉搜索树的第k个节点
给定一棵二叉搜索树,请找出其中的第k小的节点。
解析:前序遍历,回溯第k次为其值。
public class Solution {
TreeNode KthNode(TreeNode pRoot, int k)
{
TreeNode res =null;
if(pRoot==null)
return null;
int count =0;
helpNode(pRoot,res,count,k);
return res;
}
public void helpNode(TreeNode pRoot,TreeNode res,int count,int k){
if(pRoot==null)
return ;
if(res!=null)
return ;
helpNode(pRoot.left,res,count,k);
count++;
if(count==k){
res = pRoot;
return ;
}
helpNode(pRoot.right,res,count,k);
}
}
63.数据流中的中位数
解析:申明一个成员变量。
64.滑动窗口的最大值
解析:没啥特点。
65.矩阵中的路径
解析:类似于深度优先遍历的思路。
66.机器人的运动范围
解析:这种类似于点的不可达问题很多都能向深度优先遍历上靠。
public class Solution {
public int movingCount(int threshold, int rows, int cols)
{
int flag[][] = new int[rows][cols];
helpCount(threshold,rows,cols,flag,0,0);
int res =0;
for(int i=0;i<rows;i++){
for(int j =0;j<cols;j++){
res = res+flag[i][j];
}
}
return res;
}
public void helpCount(int threshold,int rows,int cols,int flag[][],int curx,int cury){
if(curx<0||curx>=rows||cury<0||cury>=cols)
return;
if(flag[curx][cury]==1)
return;
int rex=0;
int rey=0;
int replx = curx;
int reply = cury;
while( replx!=0){
rex = rex+replx%10;
replx = replx/10;
}
while(reply!=0){
rey = rey+reply%10;
reply = reply/10;
}
if(rex+rey>threshold)
return;
flag[curx][cury]=1;
helpCount(threshold,rows,cols,flag,curx+1,cury);
helpCount(threshold,rows,cols,flag,curx-1,cury);
helpCount(threshold,rows,cols,flag,curx,cury+1);
helpCount(threshold,rows,cols,flag,curx,cury-1);
}
}