目录
1、二维数组中的查找
题目描述:
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的
顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:
矩阵是有序的,从左下角来看,向上数字递减,向右数字递增。因此从左下角开始查找,当要查找数字比左下角数字大时
----右移,要查找数字比左下角数字小时----上移
代码实现:
public class Solution {
public boolean Find(int target, int [][] array) {
int len = array.length-1;//数组的一维长度
int i = 0;//控制列数
while (len >= 0 && i < array[0].length){
if(array[len][i] > target){
len--;
}else if(array[len][i] < target){
i++;
}else{
return true;
}
}
return false;
}
}
2、替换空格
题目描述:
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串
为We%20Are%20Happy。
思路:
方法一:开辟一个字符串替换
方法二:在当前字符串替换,怎么替换才更有效率(不考虑java里现有的replace方法)。从前往后替换,后面的字符要不
断往后移动,要多次移动,所以效率低下。从后往前,先计算需要多少空间,然后从后往前移动,则每个字符只为移动一
次,这样效率更高一点。
代码实现:
public class Solution {
//方法一:开辟一个新的字符串做替换
public String replaceSpace1(StringBuffer str) {
String s = str.toString();
char[] strchar = s.toCharArray();
StringBuffer a = new StringBuffer();
for(int i=0;i<strchar.length;i++){
if(strchar[i]==' '){
a.append("%20");
}
else{
a.append(strchar[i]);
}
}
return a.toString();
}
//方法二:在当前字符串做替换
public String replaceSpace2(StringBuffer str) {
//这个是使用java提供的函数进行解决。
//String str2 = str.toString();
//return str2.replace(" ","%20");
//第二种则是使用StringBuffer提供的特性解决
int spaceNum = 0;//计算空格的数量
for(int i = 0; i < str.length(); i ++){
if(str.charAt(i) == ' '){
spaceNum ++;
}
}
int oldLen = str.length();//原str的长度
int oldIndex = oldLen - 1;//这个是原str的最后一个的下标
int newLen = oldLen + spaceNum * 2;//这个新的替换空格后的str的长度
int newIndex = newLen - 1;//这个是新的str的最后一个字符的下标。
str.setLength(newLen);//设置新的长度
for(int j = oldIndex; j >=0 && j < newIndex; j--){
if(str.charAt(j) == ' '){
str.setCharAt(newIndex--, '0');
str.setCharAt(newIndex--, '2');
str.setCharAt(newIndex--, '%');
}else{
str.setCharAt(newIndex--, str.charAt(j));
}
}
return str.toString();
}
}
3、从头到尾打印链表
题目描述:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
思路:采用栈或者递归的思想来实现该ArrayList,栈的思想是先进后出,从而实现反向输出。采用递归的思想其实也是实
现先进后出的思想。做这道题首先要知道链表的数据结构,然后具体思想和步骤见代码。
代码实现:
/**
* 3、从头到尾打印链表
* 题目描述:
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
*/
//方法一:先输入这个链表从头到尾的顺序,然后使用Collection自带的反转函数
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<Integer>();
while (listNode != null) {
list.add(listNode.val);
listNode = listNode.next;
}
Collections.reverse(list);
return list;
}
//方法二:采用递归的思想
public ArrayList<Integer> printListFromTailToHead1(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<Integer>();
if (listNode != null) {
//当节点不为空的时候,指向listNode的next域,
//直到listNode的next域为空,返回list
//此时在做前一个的printListFromTailToHead(listNode.next)的递归
//即最后一个节点,此时执行一行代码,添加节点值,输出节点
//再返回到上一个递归,以此列推,直至结束。
list=printListFromTailToHead(listNode.next);
list.add(listNode.val);
}
//直到listNode的next域为空,返回list
return list;
}
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
4、重建二叉树
题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都
不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:每次都让得到一个 根节点,然后让根节点指向其左右节点。左右节点有分别有自己的根节点。一次类推,递归到
最后没有左右节点为止为出口。
代码实现:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
TreeNode root = reConstructBinaryTree(pre, 0, pre.length - 1,
in, 0,in.length - 1);
return root;
}
// 前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
private TreeNode reConstructBinaryTree(int[] pre, int startPre,
int endPre,int[] in, int startIn, int endIn) {
if (startPre > endPre || startIn > endIn)
return null;
TreeNode root = new TreeNode(pre[startPre]);
for (int i = startIn; i <= endIn; i++)
if (in[i] == pre[startPre]) {
root.left = reConstructBinaryTree(pre, startPre + 1, startPre
+ i - startIn, in, startIn, i - 1);
root.right = reConstructBinaryTree(pre, i - startIn + startPre
+ 1, endPre, in, i + 1, endIn);
break;
}
return root;
}
5、用两个栈实现队列
题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:首先需要了解栈的数据结构,先进后出,那么用两个栈实现队列。入队列:直接压入元素至s1
出队列:如果s2不为空,把s2中的栈顶元素直接弹出,否则把s1中的所有元素弹出并依次压入s2,再弹出s2中的栈顶元素
代码实现:
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
if (stack1.isEmpty()) {
while (stack2.size() != 0) {
stack1.push(stack2.pop());
}
stack1.push(node);
} else {
stack1.push(node);
}
}
public int pop() {
if (stack2.isEmpty()) {
while (stack1.size() != 0) {
stack2.push(stack1.pop());
}
return stack2.pop().intValue();
} else {
return stack2.pop().intValue();
}
}
6、旋转数组的最小数
题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个
旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所
有元素都大于0,若数组大小为0,请返回0。
思路:这个问题的中心思想其实就是使用二分查找的方法,逐步的逼近这个最小值,首先这个旋转数组将一个非递减的数
组分成了两个子数组,前一个数组的值都比后一个数组的值大,并且两个子数组都是非递减的数组,而且我们可以知道这
个最小值肯定是在前一个数组和后一个数组的交界出。也就是后一个数组的第一个值。(仔细讲解)
代码实现:
public int minNumberInRotateArray(int[] array) {
if (array.length == 0) {
return 0;
}
int low = 0;
int high = array.length - 1;
while (low < high) {
int mid = low + (high - low) / 2;
if (array[mid] > array[high]) {
low = mid + 1;
} else if (array[mid] == array[high]) {
high = high - 1;
} else {
high = mid;
}
}
return array[low];
}
7、斐波那契数列
题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项
为0)。n<=39
思路:
代码实现:
8、跳台阶
题目描述: 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序
不同算不同的结果)
思路:
代码实现:
9、变态跳台阶
题目描述: 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有
多少种跳法。
思路:
代码实现:
10、矩阵覆盖
题目描述:我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩
形,总共有多少种方法?
思路:
代码实现:
11、二进制中1的个数
题目描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路:
代码实现:
12、求1+2+3+...+n
题目描述:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
思路:1
.需利用逻辑与的短路特性实现递归终止。
2
.当n==
0
时,(n>
0
)&&((sum+=Sum_Solution(n-
1
))>
0
)只执行前面的判断,为
false
,然后直接返回
0
;
3
.当n>
0
时,执行sum+=Sum_Solution(n-
1
),实现递归计算Sum_Solution(n)。
代码实现:
public int Sum_Solution(int n) {
int sum = n;
boolean b = (sum > 0) && ((sum += Sum_Solution(sum-1))>0);
return sum;
}