剑指java~python实现

面试题:斐波那契数列

描述:一只青蛙上楼梯,一次可以上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"));
    }
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值