1.二维数组查找
题目:在一个二维数组中,每一行的数从左到右递增,每一列的数从上到下递增。输入这样的一个数组和一个整数,判断数组中是否含有该整数。
分析:先比右上角的或左下角的,如果要找的数比这个数小,剔除这一列,比较前一列的第一个数。如果大,去除这一行,再比较该列下一个数。 【先比左上角或右下角的是不行的】
public class Solution {
//判断何时找到
public static boolean Find(int target, int [][] array) { //也可以不使用静态,主方法调用时实例化
int row = 0;
int col =array[0].length-1;
while(row < array.length && col >= 0){ //二维数组中array.length表示行
if(target == array[row][col]){
return true;
}else if(target > array[row][col]){
row ++;
}else{
col --;
}
}
return false;
}
//要求客户输入二维数组
public static int[][] input(){
Scanner sc = new Scanner(System.in);
System.out.println("请输入二维数组的行数: ");
int rowNum = sc.nextInt();
System.out.println("请输入二维数组的列数: ");
int colNum = sc.nextInt();
int[][] array = new int[rowNum][colNum];
if(rowNum != 0 && colNum != 0){
for(int i=0;i<rowNum;i++){
System.out.println("请输入第" + (i+1) + "行" + colNum + "个数");
for(int j=0;j<colNum;j++){
array[i][j] = sc.nextInt();
}
}
return array;
}else{
System.out.println("输入错误---数组为空!");
return null;
}
}
public static void main(String[] args){
int[][] array = input();
if(array != null){
System.out.println("请输入要查找的数字:");
Scanner in = new Scanner(System.in);
int target = in.nextInt();
if(Find(target,array)){
System.out.println("存在!");
}else{
System.out.println("不存在!");
}
}
}
}
结果:编译通过!
2、替换空格
题目:请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为 We%20Are%20Happy。
分析:【一个换三个】
思路1:用另一个String进行复制或者替换比较方便。
思路2:先统计空格数量,确定扩长后的String总长度,一个指针a在原始字符串末尾,一个指针b在扩长后的字符串末尾。向前移动a,把字符复制给b,直到遇到空格。
时间复杂度:O(n)
思路3:遇到空格就后移字符,不提倡。复杂度O(n*n)。所以如果合并字符串或者数组时从前往后复制需要移动字符很多次,考虑时间复杂度是否可以优化,即为思路一。
/**
* 实现空格的替换
* we are happy.---->we%20are%20happy.
*
* @author Mona
*
*/
public class AlgorithmTest {
/**
* 使用StringBuffer而不是String是因为String长度不可变
*
* @param arr
* @return
*/
public String replaceSpace(StringBuffer str) {
if(str == null) {
return null;
}
int length = str.length();
int originalLength = length-1;
//首先计算出新的长度--加了空格*2的长度
for(int i=0;i<str.length();i++) {
if(str.charAt(i) == ' ') {
length += 2;
}
}
str.setLength(length);
int newLength = length-1;
while(newLength > originalLength) {
if(str.charAt(originalLength) != ' ') {
str.setCharAt(newLength--, str.charAt(originalLength));//新(最右)索引减1,即左移一位
}else {
str.setCharAt(newLength--, '0');
str.setCharAt(newLength--, '2');
str.setCharAt(newLength--, '%');
}
originalLength--; //原索引减1,即左移一位
}
return str.toString();
}
/**
* 输入为null
*/
public void test1() {
System.out.print("Test1:");
StringBuffer sBuffer = null;
String s = replaceSpace(sBuffer);
System.out.println(s);
}
/**
* 输入为空字符串
*/
public void test2() {
System.out.print("Test2:");
StringBuffer sBuffer = new StringBuffer("");
String s = replaceSpace(sBuffer);
System.out.println(s);
}
/**
* 输入字符串无空格
*/
public void test3() {
System.out.print("Test3:");
StringBuffer sBuffer = new StringBuffer("abc");
String s = replaceSpace(sBuffer);
System.out.println(s);
}
/**
* 输入字符串为首尾空格,中间连续空格
*/
public void test4() {
System.out.print("Test4:");
StringBuffer sBuffer = new StringBuffer(" a b c ");
String s = replaceSpace(sBuffer);
System.out.println(s);
}
public static void main(String[] args) {
AlgorithmTest at = new AlgorithmTest();
at.test1();
at.test2();
at.test3();
at.test4();
}
}
3.反向打印链表
题目:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
分析:
1、栈(先进后出)
2、递归(层数太深容易溢出),访问到一个节点后,递归输出它后面的节点,再输出该节点自身
import java.util.Stack;
import java.util.ArrayList;
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(listNode == null) {
return list;
}
Stack<ListNode> stack = new Stack<ListNode>();//准备栈 --- 装入每个节点
while(listNode != null) {
stack.push(listNode);
listNode = listNode.next; //把下一个节点赋值给它,一个一个push进栈
}
while(!stack.isEmpty()) {
list.add(stack.pop().val); //把弹出栈的元素加入到准备好的ArrayList列表中,即为倒序
}
return list;
}
}
//测试
public static void main(String[] args) {
ListNode list = new ListNode(0);
Solution s = new Solution();
ArrayList<Integer> list11 = s.printListFromTailToHead(list);
list11.add(1);
list11.add(2);
list11.add(3);
System.out.println(list11);
}
4.重建二叉树
题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重 复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:先找出根节点,然后利用递归方法构造二叉树
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
import java.util.Arrays;
//二叉树有左右儿子
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) { //前序遍历结点,中序遍历结点
//注意null判断,为空(“ ”)判断【拓展:isEmpty判断】
if(pre == null || in == null || pre.length == 0 || in.length == 0 || pre.length != in.length){
return null;
}
TreeNode root = new TreeNode(pre[0]);
for(int i=0;i<pre.length;i++) {
if(pre[0] == in[i]) { //寻找根结点,找到根结点在中序遍历的位置,分出左右子树
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;
}
}
五.用两个栈实现队列
题目描述:用两个栈来实现一个队列,完成队列的push和pop操作。 队列中的元素为int类型。
分析:一个栈压入元素,而另一个栈作为缓冲,将栈1的元素出栈后压入栈2中。也可以将栈1中的最后一个元素直接出栈,而不用压入栈2中再出栈。
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() throws Exception{
if(stack1.isEmpty() && stack2.isEmpty()){
throw new Exception("栈为空!"); //也可以让返回值为-1,通过
}
if(stack2.isEmpty()){
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}
参考博客:https://blog.csdn.net/baiye_xing/article/details/78428561