剑指Offer系列之题1~题5
写在前面:本随笔中包含五道题:题目描述,题目思路以及对应解法。后续该系列的随笔结构与之相同。
1.二维数组的查找
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
找到最大或最小值,然后以此为界,进行查找。
1、暴力解:
public class Solution {
public boolean Find(int target, int [][] array) {
int n=array[0].length;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(array[i][j]==target){
return true;
}
}
}
return false;
}
}
2、从左下开始比较:
public class Solution {
public boolean Find(int target, int [][] array) {
int rowLen=array[0].length;//列数
int colLen=array.length;//行数
//从左下角开始,大于则向右找,小于则向上
int j=0;
for(int i=colLen-1;i>=0;i--){
if(j<rowLen){
if(target>array[i][j]){
j++;
i++;//右移,i不变,该步抵消i--
}else if(target==array[i][j]){
return true;
}
}
}
return false;
}
}
2.替换空格
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
重点是考虑边界问题,全为空格;末尾有空格等情况
1、遍历:
public class Solution {
public String replaceSpace(StringBuffer str) {
String demo=str.toString();
String temp="";
for(int i=0;i<demo.length();i++){
if(demo.charAt(i)==' '){
temp+="%20";
}else{
temp+=demo.charAt(i);
}
}
return temp;
}
}
2、如果要求在原字符串上进行操作。则先计算新字符串的长度进行扩展。然后从后向前依次替换空格。
public class Solution {
public String replaceSpace(StringBuffer str) {
int spaceNum=0;
//计算空格数量,
for(int i=0;i<str.length();i++){
if(str.charAt(i)==' '){
spaceNum++;
}
}
int indexOld=str.length()-1;
str.setLength(str.length()+spaceNum*2);
int indexNew=str.length();//扩容后长度
for(int i=indexNew-1;i>=0 && indexOld>=0;i--){//从末尾开始
if(str.charAt(indexOld)==' '){
str.setCharAt(i,'0');
str.setCharAt(i-1,'2');
str.setCharAt(i-2,'%');
i=i-2;
indexOld--;
}else{
str.setCharAt(i,str.charAt(indexOld));
indexOld--;
}
}
return str.toString();
}
}
3.从尾到头打印链表
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
暴力解或递归
1、暴力解:
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> al=new ArrayList<Integer>();
if(listNode==null){//判空
return al;
}
al.add(listNode.val);
while(listNode.next!=null){
listNode=listNode.next;
al.add(listNode.val);
}
ArrayList<Integer> result=new ArrayList<Integer>();
for(int i=al.size()-1;i>=0;--i){
result.add(al.get(i));
}
return result;
}
}
//注:ArrayList的add(int index,E element)方法在添加时会将index处元素后移
2、递归:
import java.util.*;
public class Solution {
ArrayList<Integer> list = new ArrayList();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
//从最后一个节点开始加入列表
if(listNode!=null){
printListFromTailToHead(listNode.next);
list.add(listNode.val);
}
return list;
}
}
4.链表中环的入口节点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
先判断是否有环(快慢指针,相遇则有环),若有环,则令两个指针,一个从头节点,一个从相遇点分别开始走,再次相遇的点即环的入口节点。
1、双指针:
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead==null||pHead.next==null){
return null;
}
//判断有无环
ListNode slow=pHead;
ListNode fast=pHead;
boolean flag=false;
while(fast!=null&&fast.next!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
flag=true;
}
break;
}
//两者相遇时循环结束,此时开始计算环中结点的数目
int count=0;
while(fast.next!=slow){
count++;
fast=fast.next;
}
count++;//环的节点数
ListNode fir=pHead;
ListNode sec=pHead;
for(int i=0;i<count;i++){
fir=fir.next;
}//第一个指针走了count步
//两者开始一起走,相遇的点即入口点。第二个指针与入口点的距离=总结点数-环中的结点数
//因为第一个指针走了环中结点数,所以两者必在入口点相遇。第二个指针到达入口节点时第一个指针走了一圈到达入口结点。
while(fir!=sec){
fir=fir.next;
sec=sec.next;
}
return fir;
}
5.重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
一般情况下树的题目都可以考虑递归方法,找到递归的退出条件(本题即:前序和中序序列只剩下一个节点),在完成的基础上对代码进行优化。
1、递归:
/**
* 递归解决
* 跳出条件是只剩下一个节点,返回赋值给上一个根节点的左或右子树
* @param pre
* @param in
* @return
*/
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
//前序:根左右;中序:左根右
/*if(pre==null || in == null ){
return null;
}*/
TreeNode root=new TreeNode(pre[0]);//根节点
if(pre.length==in.length && pre.length==1){//若前序和中序遍历都只剩下一个节点则返回该节点
return root;
}
int mid=0;
//找到中序遍历中根节点的位置
for(int i=0;i<in.length;i++){
if(in[i]==root.val){
mid=i;
}
}
int left=mid;//左子树的节点个数
int right=in.length-mid-1;//右子树的节点个数
//递归
if(left>0){
int leftpre[]=new int[left];
int leftin[]=new int[left];
for(int i=0;i<left;i++){
leftpre[i]=pre[i+1];
leftin[i]=in[i];
}
root.left=reConstructBinaryTree(leftpre,leftin);//左子树的前序遍历和左子树的中序遍历
}
if(right>0){
int rightpre[]=new int[right];
int rightin[]=new int[right];
for(int i=0;i<right;i++){
rightpre[i]=pre[i+1+left];
rightin[i]=in[i+left+1];
}
root.right=reConstructBinaryTree(rightpre,rightin);//右子树的前序遍历和左子树的中序遍历
}
return root;
}
2、递归精简版:
public TreeNode reConstructBinaryTree1(int [] pre,int [] in) {
TreeNode root=reConstructBinaryTree1(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 reConstructBinaryTree1(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]){
/*startPre+i-startIn是startPre+左子树的节点个数 得到前序序列的末尾位置*/
root.left=reConstructBinaryTree1(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
root.right=reConstructBinaryTree1(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
break;
}
return root;
}
如有错误,欢迎指正
剑指Offer系列之题1~题5的更多相关文章
- 干货 | 剑指offer系列文章汇总
下面是名企面试中经常会出现的面试题目,大家可以戳相应的题目查看题目细节,其答案会在紧接着的后一篇中出现 剑指offer系列 始 剑指offer—灯管问题(1) 剑指offer—10人电梯(2) ...
- 剑指offer——python【第54题】字符流中第一个不重复的字符
题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中读出 ...
- 7、斐波那契数列、跳台阶、变态跳台阶、矩形覆盖------------>剑指offer系列
题目:斐波那契数列 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). f(n) = f(n-1) + f(n-2) 基本思路 这道题在剑指offe ...
- 剑指Offer系列之题16~题20
目录 16.反转链表 17.合并两个排序的链表 18.树的子结构
- 剑指offer——python【第60题】把二叉树打印成多行
题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行.#类似于二维列表[[1,2],[4,5]] 解题思路 其实这倒题和其他类似的题有所区别,这里是分层打印,把每层的节点值放在同一 ...
- 剑指offer——python【第28题】数组 中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- 《剑指offer》第二十六题(树的子结构)
// 面试题26:树的子结构 // 题目:输入两棵二叉树A和B,判断B是不是A的子结构. #include <iostream> struct BinaryTreeNode { doubl ...
- 剑指offer——python【第21题】栈的压入、弹出序列
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- 《剑指offer》第十九题(正则表达式匹配)
// 面试题19:正则表达式匹配 // 题目:请实现一个函数用来匹配包含'.'和'*'的正则表达式.模式中的字符'.' // 表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次).在本题 ...
随机推荐
- JavaScript实现树结构(二)
JavaScript实现树结构(二) 一.二叉搜索树的封装 二叉树搜索树的基本属性: 如图所示:二叉搜索树有四个最基本的属性:指向节点的根(root),节点中的键(key).左指针(right).右指 ...
- eetcode必要技巧--动态规划(一)
首先我们要搞清楚什么是动态规划 动态规划是运筹学中用于求解决策过程中的最优化数学方法.当然,我们在这里关注的是作为一种算法设计技术,作为一种使用多阶段决策过程最优的通用方法. 当然这个很难理解,但是按 ...
- nes 红白机模拟器 第7篇 编译使用方法
模拟器,基于 InfoNES ,作者添加修改以下功能: 1, joypad 真实手柄驱动程序(字符型设备驱动) 2,原始图像只有256*240 ,添加 图像放大算法,这里实现了2种,a, 最近邻插值 ...
- 使用synchronized修饰静态方法和非静态方法有什么区别
前言 最近被问到了这个问题,第一次回答的也是很不好,在此参考网上答案进行整理记录.供大家学习参考. Synchronized修饰非静态方法 Synchronized修饰非静态方法,实际上是对调用该方法 ...
- Scrapy 入门教程
Scrapy 是用 Python 实现的一个为了爬取网站数据.提取结构性数据而编写的应用框架. Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 通常我们可以很简单的通过 ...
- 我要打十个!详解建造者模式(builder pattern)
前言 "我要打十个",其实是我要打十个野怪! 这十个野怪呢,它们有不同的技能.装备和武器,长得也不一样.这里野怪是一个蛮复杂的对象,由各个不同的部分组成(技能.装备.武器等),不同 ...
- js 任意值变化封装
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 13.浏览器屏幕缩放bug修复
目录 问题:浏览器缩放时,轮播图显示不全,滚动水平滚动条,发现图片缺失 解决:隐藏水平滚动条,页面都只提供垂直滚动条的需求 问题:浏览器缩放时,轮播图显示不全,滚动水平滚动条,发现图片缺失 解决:隐藏 ...
- (转)const的内部链接属性(C++中适用)
转载自:http://xiangwangfeng.com/2011/05/02/const%E7%9A%84%E5%86%85%E9%83%A8%E9%93%BE%E6%8E%A5%E5%B1%9E% ...
- 解决vue在控制台的 NavigationDuplicated 报错
解决问题: 点击相同的链接,会有一个重复key的报错 const originalPush = Router.prototype.push Router.prototype.push = functi ...