前言:当前内容只用来回忆复习,java编写,代码尽可能带注释,部分题目附上解题思路。如有错误,请指出,谢谢。
1、二维数组中的查找
题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
public class Solution {
public boolean Find(int target, int [][] array) {
// 若array为null或者里面没内容,直接返回false
if(array == null || array.length == 0 || array[0].length == 0){
return false;
}
// 若target比二维数组最小值还小,即左上或二维数组最大值还大,即右下,则没有该整数,否则继续查找
int width = array[0].length;
int height = array.length;
if(target < array[0][0] || target > array[height-1][width-1]){
return false;
}
int i = 0;
int j = width -1;
while(i <= height-1 && j >= 0){
if(target == array[i][j]){
return true;
}
else if(target > array[i][j]){
i++; // 若当前值比target小,往下走
}
else{
j--; // 若当前值比target大,往左走
}
}
return false; // 遍历完数组还没有匹配,返回false
}
}
2、替换空格
题目描述
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
2.1、按C++思路编写,在原字符串缓冲区上改写
public class Solution {
public String replaceSpace(StringBuffer str) {
String ret = null;
// null返回
if(str == null){
return ret;
}
// 从后往前遍历,碰到空格,空格后所有字符依次后移2位
// 需要一次遍历,计算空格数,原长度+空格数*2就是新的字符串长度
int length = str.length();
int count = 0; // 空格计数
int pos = 0;
while(pos < length){
if(str.charAt(pos++) != ' '){ // 循环一次,pos后移
continue; // 碰到空格,直接执行下一次循环
}
count++; // 碰到空格,计数+1
}
String preStr = "%20";
int newLength = length + 2 * count;
str.setLength(newLength); // 扩充字符串缓冲区长度
pos = length-1; // 原字符串游标
int p = length -1; // 游标
int newP = newLength - 1; // 扩充后的字符串游标
while(pos >= 0){
if(str.charAt(pos) != ' '){
pos -= 1;
continue; // 没碰到空格,跳过继续循环
}
else{
// 碰到了空格,空格后依次后移2位
//int p = length-1; // 每一次替换这个位置都会变
//int newP = newlength - 1;
while(p > pos ){
str.setCharAt(newP--, str.charAt(p--));
}
// 插入待替换字符串
int rpos = preStr.length() - 1;
while(rpos>=0){
}
// 替换完成后,pos应该-1,并且应该保存位置以作为下一次替换的起点
pos -= 1;
p = pos;
}
}
ret = str.toString();
return ret;
}
}
2.2、利用StringBuffer 生成新的字符串
public class Solution {
public String replaceSpace(StringBuffer str) {
String ret = null;
// null返回
if(str == null){
return ret;
}
String srcStr = str.toString();
StringBuffer sb = new StringBuffer();
for(Character c : srcStr.toCharArray()){
if(!c.equals(' ') ){
sb.append(c);
}
else{
sb.append("%20");
}
}
ret = sb.toString();
return ret;
}
}
3、从尾到头打印链表
题目描述
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list = new ArrayList<>();
if(listNode == null){
return list; // 若listNode为null直接返回
}
while(listNode != null){
list.add(0, listNode.val); // 每访问一个结点就数组列表前插
listNode = listNode.next; // 转到下一个结点
}
return list;
}
}
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; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
// 判断任一个序列为空或者两个序列长度不等就返回null
if(pre == null || in == null || pre.length != in.length ){
return null;
}
return this.reConstructTree(pre, 0, pre.length, in, 0, in.length );
}
public TreeNode reConstructTree(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inEnd){
// 以前序的起始元素查找中序的重复元素,找到左右子树位置,并切分
int candi = pre[preStart];
int i = inStart; // 初始化切分位置
for(; i < inEnd; i++){
if(in[i] == candi){
break;// 查找到了切分位置,退出循环
}
}
// 遍历中序仍没有找到重复元素,则无法重建二叉树,返回null
if(i == inEnd ){
return null;
}
TreeNode root = new TreeNode(candi);
// 若pre和in中都只有一个元素,则直接返回
if(preStart == preEnd-1 && inStart == inEnd-1){
return root;
}
// 注意切分长度
int len = i - inStart;
// 若中序中找到重复元素位置恰好为中序范围的第一个元素,则没有左子树
if(i != inStart){
// 左子树的前序序列除去起始元素
root.left = reConstructTree(pre, preStart + 1, preStart + len + 1, in, inStart, i);
}
// 若中序中找到重复元素位置恰好为中序范围的最后一个元素,则没有右子树
if(i != (inEnd - 1) ){
// 右子树的中序序列除去重复元素
root.right = reConstructTree(pre, preStart + len+1, preEnd, in, i + 1, inEnd );
}
return root;
}
}
小问题:因为是一棵树的前序和中序是正确遍历所以可以重建,如果前序和中序序列有问题呢
5、用两个栈实现队列
题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>(); // stack2满了,再存入stack1中
Stack<Integer> stack2 = new Stack<Integer>(); // 队列入队优先存入stack2中,
// 以上说明,stack1的栈顶作为优先队头,stack2的栈底作为次级队头,stack2的栈顶作为队尾
public void push(int node) {
stack2.push(node);
}
public int pop() {
if(!stack1.isEmpty() ){
return stack1.pop();
}
else{
while(!stack2.isEmpty() ){
int ret = stack2.pop();
stack1.push(ret);
}
return stack1.pop();
}
}
}