面试题:斐波那契数列
描述:一只青蛙上楼梯,一次可以上1层,一次可以上2层,一次可以上3层,上N层有多少种跳法。
思路:上一层有1种跳法,上两层有2种跳法,上三层有4种跳法{1,1,1}{1,2}{2,1}{3},接下来就是递归
/*
* 时间复杂度3的N次方
*/
private static longf1(int n) {
if(n == 1) return 1;
if(n == 2) return 2;
if(n == 3) return 4;
return f1(n-1) + f1(n-2) + f1(n-3);
}
python的两种实现方式:
#https://www.cnblogs.com/panlq/p/9307203.html
#递推法
def fib_loop_for(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
def fib_loop_while(n):
a, b = 1, 1
while n > 0:
a, b = b, a + b
n -= 1
return a
for i in range(20):
print(fib_loop_for(i), end=' ')
#生成器
def fib_yield_while(max):
a, b = 0, 1
while max > 0:
a, b = b, a+b
max -= 1
yield a
def fib_yield_for(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
yield a
for i in fib_yield_for(10):
print(i, end=' ')
面试题4:替换空格为%20
Java实现–StringBuffer
//代码来源于:https://blog.csdn.net/ccstargazing/article/details/81119640
private static StringBuffer replaceBlank(String str) {
//先初始化一个新的可变字符串
StringBuffer sb = new StringBuffer();
int len = str.length();
for(int i = 0; i < len; i++){
char ch = str.charAt(i);
//逐个判断原字符串,若是空格,则转换成%20,加到新字符串,若不是空格,直接加到新的字符串
if(ch != ' '){
sb.append(ch);
} else {
sb.append("%20");
}
}
return sb;
}
public static void main(String[] args) {
System.out.println(replaceBlank("We are happy"));
}
Java实现–replace
public String replaceSpace(StringBuffer str) {
return str.toString().replace(" ","%20");
}
python实现–正则表达式
import re
def replaceSpace(self, s):
return re.sub(r' ', '%20', s)
Python实现–replace
def replaceSpace(s):
# return s.replace(" ","%20",s.count(" "))
return s.replace(' ','%20')
面试题5:从头到尾打印链表
Java实现
//参考:https://blog.csdn.net/weixin_37672169/article/details/80164733
/**
* 调整数组顺序使奇数位于偶数前面
*/
public class OddEventArray {
public void reorderOddEvent(int[] array){
if(array == null || array.length == 0){
return ;
}
int len = array.length;
int low = 0;
int high = len - 1;
while(low <= high){
while(!isEvent(array[low]) && low <= len - 1){
low++;
}
while(isEvent(array[high]) && high >= 0){
high--;
}
if(low <= high){
int temp = array[low];
array[low] = array[high];
array[high] = temp;
}
}
}
//判断是否是偶数,true:偶数;false:奇数
public boolean isEvent(int num){
return (num & 1) == 0;
}
public static void main(String[] args) {
OddEventArray test = new OddEventArray();
int[] array = {2,1};
System.out.println(Arrays.toString(array));
test.reorderOddEvent(array);
System.out.println(Arrays.toString(array));
}
}
面试题:重建二叉树
已知前序遍历和中序遍历的结果,重建二叉树
Java实现:
class TreeNode {
int value;
TreeNode leftTree;
TreeNode rightTree;
TreeNode(int x) { value = x; }
@Override
public String toString() {
return "TreeNode{" +
"value=" + value +
", leftTree=" + leftTree +
", rightTree=" + rightTree +
'}';
}
}
import java.util.Arrays;
public class JzOffer4 {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre.length == 0 || in.length == 0) {
return null;
}
// 先根据先序遍历建立根结点
TreeNode root = new TreeNode(pre[0]);
for (int i=0;i<in.length;i++) {
if (in[i] == pre[0]) {
/**
* 递归构建左右子树
* 注意 copyOfRange 函数,左闭右开
*/
root.leftTree = reConstructBinaryTree(Arrays.copyOfRange(pre, 1,i+1 ), Arrays.copyOfRange(in, 0, i));
root.rightTree = reConstructBinaryTree(Arrays.copyOfRange(pre, i+1, pre.length), Arrays.copyOfRange(in, i+1, in.length));
break;
}
}
return root;
}
public static void main(String[] args) {
int[] pre = {1,2,4,7,3,5,6,8};
int[] in = {4,7,2,1,5,3,8,6};
System.out.println(new JzOffer4().reConstructBinaryTree(pre,in).toString());
}
}
python实现
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
prelen = len(pre)
tinlen = len(tin)
if prelen == 0 | tinlen == 0 :
return None
root = TreeNode(pre[0])
for i in range(tinlen):
if tin[i] == pre[0]:
root.left = self.reConstructBinaryTree(pre[1:i+1], tin[0:i])
root.right = self.reConstructBinaryTree(pre[i+1:prelen], tin[i+1:tinlen])
break
return root
用栈实现队列
队列:先进先出
栈:先进后出
Java实现(in 栈先进+ out先进在后面–>先进后出)
//https://blog.csdn.net/weixin_44285445/article/details/108134618?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-4.control
import java.util.Stack;
public class JzOffer5 {
Stack<Integer> in = new Stack<Integer>();
Stack<Integer> out = new Stack<Integer>();
public void push(int node){
in.push(node);
}
public int pop(){
if (out.isEmpty()) {
while (!in.isEmpty()) {
out.push(in.pop());
}
}
return out.pop();
}
}
Python实现:
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, node):
# write code here
self.stack1.append(node)
def pop(self):
# return xx
if len(self.stack2) == 0:
while len(self.stack1) != 0:
self.stack2.append(self.stack1.pop())
return self.stack2.pop()
翻转i am a student------>>>student a am i
Java实现:先单个单词反转,再整体反转。
I am a student. —> I ma a .tneduts —> student. a am I
public class Solution {
public String ReverseSentence(String str)
{
//先单个单词反转,再整体反转。I am a student.》》I ma a .tneduts 》》student. a am I
if(str.length()==0)
return str;
char[]chs=str.toCharArray();
//对单个字符数组元素进行反转
int i=0,j=0;//定义两个指针进行遍历
while(j<=str.length()){
//以空格作为区分,对每个单词进行反转
if(j==str.length()||chs[j]==' '){//j==str.length()不要忘记
reverse(chs,i,j-1);
i=j+1;
}
//如果chs[j]!=' '那么继续遍历直到找到空格
j++;
}
//整体字符串反转
reverse(chs,0,str.length()-1);
return new String(chs);//学习
}
private void reverse(char[]ch,int i,int j){
while(i<j){
//反转交换,代码是一样的
char temp=ch[i];
ch[i]=ch[j];
ch[j]=temp;
i++;
j--;
}
}
}
python实现:
在这里插入代码片
数字在排序数组中出现的次数
java实现
//方法一:非排序数据中
public static void main(String[] args) {
int[] arr = {1,2,3,3,2,1,4,5,3,2,1};
//统计个数
//创建HashMap,key为数组中的值,value为值重复出现的次数
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<arr.length;i++){
//通过map.get()方法,获取map中是否已经存在该值,如果存在则通过key取到value并加一,否则key值为1
map.put(arr[i], map.get(arr[i]) == null?1:map.get(arr[i])+1);
}
System.out.println(map);
}
//方法二:排序数组中--二分查找
private int getFirstK(int[] arr,int k,int left,int right){
if(left > right)
return -1;
int middleIndex = (left+right)/2;
int middleData = arr[middleIndex];
if(middleData == k){
if((middleIndex >0 && arr[middleIndex -1]!=k)|| middleIndex == 0)
return middleIndex;
else
right = middleIndex -1;
}
else if(middleData > k)
right = middleIndex -1;
else
left = middleIndex +1;
return getFirstK(arr,k,left,right);
}
private int getLastK(int[] arr,int k,int left,int right){
if(left > right)
return -1;
int middleIndex = (left + right)/2;
int middleData = arr[middleIndex];
if(middleData == k){
if((middleIndex <arr.length -1 && arr[middleIndex+1]!=k) || middleIndex ==arr.length-1)
return middleIndex;
else
left = middleIndex+1;
}
else if(middleData <k){
left = middleIndex +1;
}else
right = middleIndex -1;
return getLastK(arr,k,left,right);
}
public int getNumberOfK(int[] arr,int k){
int number = 0;
if(arr.length >0){
int first = getFirstK(arr,k,0,arr.length-1);
int last = getLastK(arr,k,0,arr.length -1);
if(first >-1 && last >-1)
number =last-first+1;
}
return number;
}
方法二:
//https://blog.csdn.net/abc7845129630/article/details/52742526?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-5.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-5.control
public class Solution {
public int GetNumberOfK(int [] array , int k) {
if(array==null||array.length==0){
return 0;
}
int res=0;
int len=array.length;
int l=GetFistOfK( array , k,0 , len-1);
int r=GetLastOfK(array , k,0 ,len-1 );
if(l>=0&&r>=0){
res=r-l+1;
}
return res;
}
public int GetFistOfK(int [] array , int k,int l,int r) {
if(l>r||l<0||r<0){
return -1;
}
int mid=(l+r)/2;
if(array[mid]==k){
int t=mid;
while(t>=0&&array[t]==k){
t--;
}
return ++t;
}else if(array[mid]<k){
return GetFistOfK(array , k, l, mid-1);
}else{
return GetFistOfK(array , k, mid+1, r);
}
}
public int GetLastOfK(int [] array , int k,int l,int r) {
if(l>r||l<0||r<0){
return -1;
}
int mid=(l+r)/2;
if(array[mid]==k){
int t=mid;
while(t<array.length&&array[t]==k){
t++;
}
return --t;
}else if(array[mid]<k){
return GetLastOfK(array , k, l, mid-1);
}else{
return GetLastOfK(array , k, mid+1, r);
}
}
}
python中直接利用count方法
链接:https://www.nowcoder.com/questionTerminal/70610bf967994b22bb1c26f9ae901fa2
//因为data中都是整数,所以可以稍微变一下,不是搜索k的两个位置,而是搜索k-0.5和k+0.5
//这两个数应该插入的位置,然后相减即可。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
return biSearch(data, k+0.5) - biSearch(data, k-0.5) ;
}
private:
int biSearch(const vector<int> & data, double num){
int s = 0, e = data.size()-1;
while(s <= e){
int mid = (e - s)/2 + s;
if(data[mid] < num)
s = mid + 1;
else if(data[mid] > num)
e = mid - 1;
}
return s;
}
#方法二:
def GetNumberOfK(self, data, k):
if len(data) < 1:
return 0
mid = len(data)/2
if data[mid] == k:
start,end = mid, mid
for i in range(mid,-1,-1):
if data[i] == k: start -= 1
for j in range(mid+1,len(data)):
if data[j] == k: end += 1
return end - start
elif data[mid]>k:
return self.GetNumberOfK(data[:mid], k)
else:
return self.GetNumberOfK(data[mid+1:],k)
密码合格验证
paswadIsOk()
{
char s[100];
while( gets(s) )
{ int flag=0;
//第一个条件判断不满足直接后面的就不用判断了
int len=strlen(s);
if(len<=8)
{ printf("NG\n");flag=1;continue;}
//第二个条件判断,不满足则退出
int count=0,num=0,low=0,upper=0,other=0;
for(int i=0;i<len;i++)
{
if(s[i]>='0'&&s[i]<='9')
num=1;
else if(s[i]>='A'&&s[i]<='Z')
low=1;
else if(s[i]>='a'&&s[i]<='z')
upper=1;
else
other=1;
}
count=num+low+upper+other;
if(count<3)
{ printf("NG\n");flag=1;continue;}
//第三个条件判断
for(int i=0;i<=len-3;i++)
for(int k=i+3;k<len;k++)
{
if(s[i]==s[k]&&s[i+1]==s[k+1]&&s[i+2]==s[k+2])
{ printf("NG\n");flag=1;continue;}
}
//如果flag==0表示满足3个条件,所以输出ok
if(flag==0)
printf("OK\n");
}
return 0;
}
面试题38:字符串的排序(abc/acb/bac/bca/cab/cba)
//Arrays中提供了基本数据类型数组排序
String[] strs = new String[]{"abfds1", "advesd2", "dasfdsa3", "cdsaew1", "abbdsa3", "abbdsa2", "abbdsa"};
Arrays.sort(strs);
for(String str : strs) {
System.out.println(str);
}
package com.codinginterviews.str;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/**
* 题目:
* 字符串的排列 -- newcoder 剑指Offer 27
*
* 题目描述:
* 输入一个字符串,按字典序打印出该字符串中字符的所有排列。
* 例如输入字符串abc,则打印出由字符a,b,c 所能排列出来的所有字符串
* abc,acb,bac,bca,cab和cba。
*
* 输入描述:
* 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
*/
public class Permutation
{
/**
* 思路:
*
* 对于无重复值的情况
*
* 固定第一个字符,递归取得首位后面的各种字符串组合;
* 再把第一个字符与后面每一个字符交换,并同样递归获得首位后面的字符串组合; *递归的出口,就是只剩一个字符的时候,
* 递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串。
*
* 假如有重复值呢?
* 由于全排列就是从第一个数字起,每个数分别与它后面的数字交换,我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这两个数就不交换了。
* 例如abb,第一个数与后面两个数交换得bab,bba。然后abb中第二个数和第三个数相同,就不用交换了。
* 但是对bab,第二个数和第三个数不 同,则需要交换,得到bba。
* 由于这里的bba和开始第一个数与第三个数交换的结果相同了,因此这个方法不行。
*
* 换种思维,对abb,第一个数a与第二个数b交换得到bab,然后考虑第一个数与第三个数交换,此时由于第三个数等于第二个数,
* 所以第一个数就不再用与第三个数交换了。再考虑bab,它的第二个数与第三个数交换可以解决bba。此时全排列生成完毕!
*
*/
public ArrayList<String> permutation(String str) {
ArrayList<String> ret = new ArrayList<>();
if (str == null || str.isEmpty()) {
return ret;
}
char[] arr = str.toCharArray();
permutation(arr, 0, ret);
Collections.sort(ret);
return ret;
}
private void permutation(char[] arr, int begin, ArrayList<String> cache) {
if (begin == arr.length - 1) {
cache.add(new String(arr));
return;
}
int len = arr.length;
for (int i=begin; i<len; i++) {
// 与begin不同位置的元素相等,不需要交换
if (i!=begin && arr[i]==arr[begin]) {
continue;
}
// 交换元素
swap(arr, begin, i);
// 处理后续元素
permutation(arr, begin+1, cache);
// 数组复原
swap(arr, begin, i);
}
}
private void swap(char[] arr, int i, int j) {
if (i == j) {
return;
}
arr[i] = (char)(arr[i]^arr[j]);
arr[j] = (char)(arr[i]^arr[j]);
arr[i] = (char)(arr[i]^arr[j]);
}
/**
* 思路2(摘自牛客网):
*
* 字典序排列算法
*
* 可参考解析: http://www.cnblogs.com/pmars/archive/2013/12/04/3458289.html (感谢作者)
*
* 一个全排列可看做一个字符串,字符串可有前缀、后缀。
* 生成给定全排列的下一个排列.所谓一个的下一个就是这一个与下一个之间没有其他的。
* 这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。
*
* [例]839647521是1--9的排列。1—9的排列最前面的是123456789,最后面的987654321,
* 从右向左扫描若都是增的,就到了987654321,也就没有下一个了。否则找出第一次出现下降的位置。
*
* 【例】 如何得到346987521的下一个
* 1,从尾部往前找第一个P(i-1) < P(i)的位置
* 3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1
* 最终找到6是第一个变小的数字,记录下6的位置i-1
*
* 2,从i位置往后找到最后一个大于6的数
* 3 4 6 -> 9 -> 8 -> 7 5 2 1
* 最终找到7的位置,记录位置为m
*
* 3,交换位置i-1和m的值
* 3 4 7 9 8 6 5 2 1
* 4,倒序i位置后的所有数据
* 3 4 7 1 2 5 6 8 9
* 则347125689为346987521的下一个排列
*
*/
public ArrayList<String> permutationII(String str){
ArrayList<String> list = new ArrayList<String>();
if(str==null || str.length()==0){
return list;
}
char[] chars = str.toCharArray();
Arrays.sort(chars);
list.add(String.valueOf(chars));
int len = chars.length;
while(true){
int lIndex = len-1;
int rIndex;
while(lIndex>=1 && chars[lIndex-1]>=chars[lIndex]){
lIndex--;
}
if(lIndex == 0)
break;
rIndex = lIndex;
while(rIndex<len && chars[rIndex]>chars[lIndex-1]){
rIndex++;
}
swap(chars,lIndex-1,rIndex-1);
reverse(chars,lIndex);
list.add(String.valueOf(chars));
}
return list;
}
private void reverse(char[] chars,int k){
if(chars==null || chars.length<=k)
return;
int len = chars.length;
for(int i=0;i<(len-k)/2;i++){
int m = k+i;
int n = len-1-i;
if(m<=n){
swap(chars,m,n);
}
}
}
public static void main(String[] args)
{
System.out.println(new Permutation().permutation("abc"));
System.out.println(new Permutation().permutationII("abc"));
}
}