剑指offer快速回忆之面试中的各项能力

摘要

知识迁移能力、抽象建模能力、发散思维能力、树中俩节点的最低祖先、排序数组查找数字、排序数组数字出现字数、数组中唯一出现一次的数字、和为s的数字、和为s的序列、翻转单词、滑动窗口、约瑟夫环、求1加到n、不用加减乘除做加法、不用变量交换两个变量值、构建乘积数组

沟通能力

学习能力

  1. 看什么书
  2. 做什么项目
  3. 学什么新技术
  4. 给你一个概念让你理解
  5. 要学会反抛问题
1.如何求树中两个节点的最低公共祖先

这里说的概念很模糊,树。
1.二叉树
2.二叉搜索树(简单)
3.多叉树有指向父节点的指针(模型等于求两个链表的第一个公共节点)
4.多叉树(用栈保存路径)

知识迁移能力

  1. 会问一个简单问题
  2. 再问一个相关的难度更大的问题
2.在排序数组中查找数字

统计一个数字在排序数组中出现的次数。

很容易想到二分查找,只不过我之前的二分查找算法不大行
这里标准的思路是:找到了目标k先看是不是第一个,若是返回下标,若不是继续查找
3.数组中数字出现的次数

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

重点是时间O(n),空间O(1)
重点还是出现两次,位运算有个好东西叫异或,相同的数异或为0
将数组中所有的数字进行异或运算,得到值a,a肯定不为0,那么就有一位为1
我们根据这一位为1为标准,将数组分成两分,分别进行异或,就得到了最终的结果
4.数组中唯一出现一次的数字

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

拆成位运算:
	将所有数字的二进制相加(每一位都不进位),如果没有出现一次的数字,那么每一位都应该是能被3整除的
如果某一位不能被3整除,说明只出现一次的数字在这一位是1
5.和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

这道题做过一次,当时写的回溯,我枯了,时隔至少3个月中遇又让我碰到了。
这次俺用双指针。嘿嘿
6.和为s的连续正数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
.
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

这个题还是可以大小指针,小指针~大指针之间的值要是小于sum大指针加一,大于sum小指针加一
还可以数学做法,比如现在指针x,目标是sum,所以:(x+n)/2*(n-x+1)=sum,求解n。
若n是整数就打印,不是x++
7.翻转单词顺序

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
.
左反转字符串 studnet , 2 -> udentst

这题官方给的方法是,先反转整个字符串,在反转里面的每个单词
(左反转一个,只不过一个是按空格反转,一个是按长度反转)
因为他是C++,char*就是数组,然鹅,我们的String.value是不允许修改的
8.滑动窗口的最大值

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

比如:[1,3,-1,-3,5,3,6,7]
构造一个队列:
队列头部是滑动窗口的最大值,队列后边是当前滑动窗口的最大值滑出后有可能接替它的值。
从1到7模拟进出队:
1           max=1
3           max=3,因为3是滑动窗口刚加进来的值,大于1有3在,1就不可能是最大值,所以1出队了
3  -1       max=3,因为当3滑出后-1有可能是最大值,所以保留
3  -1  -3   max=3,因为3滑出,-1滑出,-3就可能是最大值了
5          ,max=5,因为3真的滑出了,而且5滑入,有5在有你们负数什么果子吃
5   3
6
7
完结,很像单调栈,单调队列?---------------------------------------------------分界线----------------
存值是不行的,应该存下标,因为存值不知道什么时候滑入的,也就不知道什么时候滑出
而存下标的话,当滑入的index-i>滑动窗口的大小就是滑出了

分界线往上是单调队列,分界线往下是滑动窗口
滑动窗口是什么?滑动窗口是一个数组,两个指针(窗口开始和结尾),一个队列(保存指针信息)
其实单调队列是应该和普通的队列一起用的,当普通的队列出队时,单调队列跟着看下是不是自己的队头出去了
但是因为滑动窗口出队动作就是index太小,所以就把普通队列和单调队列合并了(外边有个数组肯定),
你也可以理解为用数组代替了普通队列的代价,单调队列就必须存索引了

抽象建模能力

9.约瑟夫环

n个数每次删除下标为m,求最后剩下的人

常规做法是链表成环。
还一种做法是映射:
记函数f(n,m)为给出n个人依次删除m剩下的最后一个人,则删除一次后,剩下的人为
0,1,2,3,4.....m-1,m+1,....,n-1   (下次从m+1开始报数)
接下来映射:
m+1    0
m+2    1
m+3    2
...
m-1    n-2
假设映射函数为t(x)
映射后是不是等于继续求 f'(n-1,m)
...一只这么映射
知道n=1,下标为0时停止
这时候我们反过来求这个在f''''''''(1,m)下标是0的人在f(n,m) 中的索引,
只需要将t(x)的反函数带入几次不就行了吗?
简不简单?惊不惊喜?
简单求一下t(x)=(x-m-1)%n)
反函数t'(x)=(x+m+1)%n

发散思维

10.求1+2+3+4+…+n

这道题只针对C语言吧
作者用了两种方法:
…1.构造函数 A* a=new A[25]; 会自动执行A的构造函数25次?把我看呆了
…2.利用了非0的逻辑是true,true的数字是1,这样就可以把所有的非零都化成1
然后在A[]中放两个实例,一个是返回0,一个是递归调用n-1

11.不用加减乘除做加法

那只能是位运算了
思路:不考虑进位,那就是异或,
考虑进位,只有同时为1,才能产生进位,如何判断同时为1,对与运算
然后进位左移1位,在加上不考虑进位产生的结果
重复此步骤
.
不是用新的变量,交换变量的值
a=a+b
b=a-b
a=a-b

12.构建乘积数组

给定一个数组 A[0,1,…,n-1],请构建一个数组 B[0,1,…,n-1],其中 B 中的元素 B[i]=A[0]×A[1]×…×A[i-1]×A[i+1]×…×A[n-1]。不能使用除法。

如果能用除法很简单,(但是注意被除数不能为0哦)
但是不可以用,现在只能优化一点点
见下图;

B图

Bi就是第i行的乘积。
现在我们设Ci=A0*A1*...*A[i-1]
Di=A(i+1)*A(i+2)*A(i+3)*...*A(n-1)
再结合上图,Ci是不是能很快得到Ci=C(i-1)*A(i-1)
Di同理,此题结。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值