1.二维数组中的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思路:选取右上一点,若等于查找的数,则返回true,若此数大于所要查找的数,则此列都大于,不可能出现查找之数。剔除此列,以此类推。若右上角的数小于查找之数,则剔除此行。直到找到查找之数。
public class Main1 {
public static boolean findNum(int[][] array,int target) {
if(array == null) {
return false;
}
int row = 0;
int col = array[0].length - 1;
while(row < array.length && col >= 0) {
if(array[row][col] == target) {
return true;
}else if(array[row][col] > target) {
col--;
}else{
row++;
}
}
return false;
}
public static void main(String[] args) {
int[][] arr = {{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};
System.out.println(findNum(arr,7));
}
}
2.替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
思路
- 双指针法:先遍历一遍字符串,统计空格数,得出替换后长度,定义两个指针,p1指向字符串末尾,p2指向替换后末尾,把p1的内容拷贝到p2,同时减减。当p1遇到空格时,把空格替换为%20,p1向前移动一格,p2向前移动三格。
public class Main2 {
public static String replaceSpace(StringBuffer str) {
int spaceNum = 0;
for(int i = 0;i < str.length();i++) {
if(str.charAt(i) == ' '){
spaceNum++;
}
}
//记录字符串变化前后长度
int oldLength = str.length();
int newLength = str.length() + 2 * spaceNum;
//重新设置str长度
str.setLength(newLength);
//定义两个指针
int oldIndex = oldLength - 1;
int newIndex = newLength - 1;
while(oldIndex >= 0 && oldLength < newLength) {
if(str.charAt(oldIndex) == ' ') {
str.setCharAt(newIndex--,'0');
str.setCharAt(newIndex--,'2');
str.setCharAt(newIndex--,'%');
}else {
str.setCharAt(newIndex--,str.charAt(oldIndex));
}
oldIndex--;
}
return str.toString();
}
public static void main(String[] args) {
StringBuffer str = new StringBuffer("we are happy!");
System.out.println(replaceSpace(str));
}
}
- 用新的数组存:创建一个新数组,遍历字符串,当遇到空格时,插入%20,其他照搬,直至结束。
public class Main2 {
public static String replaceSpace(StringBuffer str) {
StringBuffer sb = new StringBuffer();
for(int i = 0;i < str.length();i++) {
if(str.charAt(i) == ' '){
sb.append("%20");
}else {
sb.append(str.charAt(i));
}
}
return sb.toString();
}
public static void main(String[] args) {
StringBuffer str = new StringBuffer("we are happy!");
System.out.println(replaceSpace(str));
}
}
3.从尾到头打印链表
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
思路:
- 非递归,先进后出,用栈实现
import java.util.ArrayList;
import java.util.Stack;
public class Main3 {
public class ListNode{
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList list = new ArrayList();
Stack stack = new Stack();
while(listNode != null) {
stack.push(listNode.val);
listNode = listNode.next;
}
while(!stack.empty()) {
list.add(stack.pop());
}
return list;
}
}
- ArrayList 中有个方法是 add(index,value),可以指定 index 位置插入 value 值.每次插入0号位置
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList list = new ArrayList();
while(listNode != null) {
list.add(0,listNode.val);
listNode = listNode.next;
}
return list;
}
}
- 递归解法
import java.util.ArrayList;
public class Main3 {
ArrayList list = new ArrayList();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if(listNode != null) {
printListFromTailToHead(listNode.next);
list.add(listNode.val);
}
return list;
}
}
4.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:前序遍历:根左右 ,中序遍历:左根右。前序遍历的第一个数为根,在中序遍历中找到该数,则之前的都是左子树,之后的都是右子树。运用递归的思想进行重建。
import java.util.Arrays;
public class Main4 {
public static class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public static TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length == 0 || in.length == 0) {
return null;
}
if(pre.length != in.length)
new Exception("前中序长度不同,请重新输入");
TreeNode root = new TreeNode(pre[0]);
for(int i = 0;i < in.length;i++) {
if(in[i] == pre[0]) {
root.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,i +1),
Arrays.copyOfRange(in,0,i));
root.right = reConstructBinaryTree(Arrays.copyOfRange(pre,i + 1,pre.length),
Arrays.copyOfRange(in,i + 1,in.length));
}
}
return root;
}
public static void main(String[] args) {
int[] pre = {1,2,4,7,3,5,6,8};
int[] mid = {4,7,2,1,5,3,8,6};
System.out.println(reConstructBinaryTree(pre,mid));
}
}
5.两个栈实现一个队列
用两个栈来实现一个队列,完成队列的appendTail和deleteHead操作。分别完成队列尾部插入节点和队列头部删除节点。
思路:栈为先进后出,所以尾部插入节点,就是将元素依次入栈,而删除头节点就是将第一次入栈的元素依次取出,在压入另一个栈,从第二个栈的栈顶取出要删除的节点。
import java.util.Stack;
public class Test {
private Stack<Integer> stack1 = new Stack<>();
private Stack<Integer> stack2 = new Stack<>();
public void appendTail(int node){
stack1.push(node);
System.out.println(stack1);
}
public Integer deleteHead() throws Exception {
if (stack2.isEmpty()){
while (!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
if (stack2.isEmpty()){
throw new Exception("队列为空,不能删除");
}
System.out.println(stack2);
return stack2.pop();
}
public static void main(String[] args) throws Exception {
Test test = new Test();
test.appendTail(1);
test.appendTail(2);
test.appendTail(3);
test.deleteHead();
}
}
6.旋转数组中的最小值
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
思路: 利用二分查找的方法,定义两个指针,left指向开始下标,right指向末尾下标,并求出中间值mid,若左下标对应的值小于中间值,则为递增数列,left = mid+1;若右下标对应的值大于中间值,则为递减数列,righ=mid;其他情况,left++.
注意特殊数组1,0,1,1,1,当左下标对应的值小于右下标对应的值,直接返回左下标对应的值.
public class Main6 {
public static int minNumberInRotateArray(int [] array) {
if(array.length == 1) {
return array[0];
}
int left = 0;
int mid = 0;
int right = array.length - 1;
while(left < right) {
if(array[left] < array[right])
return array[left];
mid = left + (right - left)/2;
if(array[mid] > array[left]) {
left = mid + 1;
}else if(array[mid] < array[right]) {
right = mid;
}else {
left++;
}
}
return array[left];
}
public static void main(String[] args) {
int[] array1 = {3, 4, 5, 1, 2};
System.out.println(minNumberInRotateArray(array1));
int[] array2 = {1, 0, 1, 1, 1};
System.out.println(minNumberInRotateArray(array2));
}
}
7.斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
思路:后一个值是前两个值之和
public class Main7 {
//递归版本
public static int Fibonacci1(int n) {
if(n <= 0) {
return 0;
}
if(n <= 2) {
return 1;
}else {
return Fibonacci1(n - 1) + Fibonacci1(n - 2);
}
}
//非递归版本
public static int Fibonacci2(int n) {
if(n <= 0)
return 0;
if(n ==1||n == 2)
return 1;
int a = 1;
int b = 1;
int sum = 0;
for(int i = 3;i <= n;i++) {
sum = a + b;
a = b;
b = sum;
}
return sum;
}
public static void main(String[] args) {
System.out.println(Fibonacci1(6));
System.out.println(Fibonacci2(6));
}
}
8.二进制中1的个数
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路:把一个整数减去1,在和原来的数做与运算,会把整数最右边的1变为0,那么一个数二进制中有多少个1,就有多少次操作
public class Main8 {
public static int NumberOf1(int n) {
int count = 0;
while(n != 0) {
count++;
n = n & (n - 1);
}
return count;
}
public static void main(String[] args) {
System.out.println(NumberOf1(9));
}
}