牛客网面试高频题top100(81~90)

面试高频算法题top100(81~90)java实现

81.回文数字

在不使用额外的内存空间的条件下判断一个整数是否是回文。
回文指逆序和正序完全相同。

import java.util.*;


public class Solution {
   
    public boolean isPalindrome (int x) {
        if(x<0) return false;
        long num = 0;
        int n = x;
        while(x!=0){
            num = num*10+x%10;
            x /= 10;
        }
        
        if((int)num!=n)
            return false;
        return true;
    }
}

82.二分查找(二)

请实现有重复数字的升序数组的二分查找
给定一个 元素有序的(升序)长度为n的整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的第一个出现的target,如果目标值存在返回下标,否则返回 -1
在这里插入图片描述

import java.util.*;


public class Solution {
   
    public int search (int[] nums, int target) {
        if(nums.length==0) return-1;
        int left=0,right = nums.length;
        while(left<right){
            int mid = left + (right-left)/2;
            if(nums[mid]>=target)
                right = mid;
            else
                left = mid+1;
        }
        if(nums[left]==target) return left;
        return -1;
    }
}

83.丢棋子问题

一座大楼有 n+1 层,地面算作第0层,最高的一层为第 n 层。已知棋子从第0层掉落肯定不会摔碎,从第 i 层掉落可能会摔碎,也可能不会摔碎。
给定整数 n 作为楼层数,再给定整数 k 作为棋子数,返回如果想找到棋子不会摔碎的最高层数,即使在最差的情况下扔的最小次数。一次只能扔一个棋子。
在这里插入图片描述

import java.util.*;


public class Solution {
   
    public int solve (int n, int k) {
        if(k==1) return n;
        if(k>=n) return (int)(Math.log(n)/Math.log(2))+1;
        int time = 1;
        int[] dp = new int[k+1];
        while(true){
            for(int j=k;j>0;j--){
                dp[j] = dp[j-1]+dp[j]+1;
                if(dp[j]>=n)
                    return time;
            }
            time ++;
        }
    }
}

84.序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。
在这里插入图片描述

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
import java.util.*;
public class Solution {
    String Serialize(TreeNode root) {
        if(root==null) return "# ";
        String left = Serialize(root.left);
        String right = Serialize(root.right);
        String str = String.valueOf(root.val)+" ";
        return str+left+right;
    }
    TreeNode Deserialize(String str) {
       Queue<String> que = new LinkedList<>();
        String[] temp = str.split(" ");
        for(int i=0;i<temp.length;i++)
            que.add(temp[i]);
        return recon(que);
    }
    TreeNode recon(Queue<String> que){
        String stemp = que.poll();
        if(stemp.equals("#")) return null;
        TreeNode root = new TreeNode(Integer.parseInt(stemp));
        root.left = recon(que);
        root.right = recon(que);
        return root;
    }
}

85.二叉搜索树的第K个节点

给定一棵结点数为n 二叉搜索树,请找出其中的第 k 小的TreeNode结点值。
1.返回第k小的节点值即可
2.不能查找的情况,如二叉树为空,则返回-1,或者k大于n等等,也返回-1
3.保证n个节点的值不一样
在这里插入图片描述

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    ArrayList<Integer> res = new ArrayList<>();
    public int KthNode (TreeNode proot, int k) {
        if(proot==null || k==0) return -1;
        search(proot);
        Collections.sort(res);
        if(res.size()<k) return -1;
        return res.get(k-1);
    }
    public void search(TreeNode root){
        if(root==null) return;
        res.add(root.val);
        search(root.left);
        search(root.right);
    }
}

86.字符串变形

对于一个长度为 n 字符串,我们需要对它做一些变形。首先这个字符串中包含着一些空格,就像"Hello World"一样,然后我们要做的是把这个字符串中由空格隔开的单词反序,同时反转每个字符的大小写。比如"Hello World"变形后就变成了"wORLD hELLO"。
在这里插入图片描述

import java.util.*;

public class Solution {
    public String trans(String s, int n) {
        String temp = "";
        Stack<String> stack = new Stack<>();
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)==' '){
                if(temp.length()>0)  stack.push(temp);
                stack.push(" ");
                temp = "";
            }else
                temp += Character.isLowerCase(s.charAt(i))?Character.toUpperCase(s.charAt(i)):Character.toLowerCase(s.charAt(i));
        }
        if(temp.length()>0) stack.push(temp);
        StringBuilder str = new StringBuilder();
        while(!stack.empty())
            str.append(stack.pop());
        return str.toString();
    }
}

87.数组中的最长连续子序列

给定无序数组arr,返回其中最长的连续序列的长度(要求值连续,位置可以不连续,例如 3,4,5,6为连续的自然数)
在这里插入图片描述

import java.util.*;


public class Solution {
    
    public int MLS (int[] arr) {
        Arrays.sort(arr);
        int num = 1,count = 1;
        int temp = arr[0];
        for(int i=1;i<arr.length;i++){
            if(arr[i]==temp+1)
                count ++;
            else if(arr[i]==temp)
                continue;
            else
                count = 1;
            temp = arr[i];
            num = Math.max(num,count);
                
        }
        return num;
    }
}

88.环形链表的约瑟夫问题

编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。
下一个人继续从 1 开始报数。n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?
在这里插入图片描述

import java.util.*;


public class Solution {
    public int ysf (int n, int m) {
        // write code here
        if(n==1)  return 1;
        ArrayList<Integer> list = new ArrayList<>();
        for(int i= 1;i<n+1;i++)  list.add(i);
        int index = 0;
        while(n>1){
            index = (m-1+index)%n;
            list.remove(index);
            n--;
        }
        return list.get(0);
    }
}

优化空间复杂度为O(1):

import java.util.*;


public class Solution {
    public int ysf (int n, int m) {
        // 最后剩下编号每次所在的索引
        int index=0;
       //最后一轮剩下2个人,所以从2开始反推
        // i表示环中元素个数
        for(int i=2;i<=n;i++){
            index=(index+m)%i;
        }
        return index+1;
    }

}

89.多叉树的直径

在这里插入图片描述核心就是树的最大直径(globalMax)一定是以某一个node为root最长的两个通往叶子的路。
就是普通dfs的同时算路径长度。

import java.util.*;

/**
 * public class Interval {
 *   int start;
 *   int end;
 * }
 */

public class Solution {
  Map<Integer, List<int[]>> graph = new HashMap<>();
  int globalMax = 0;
  
  public int solve (int n, Interval[] Tree_edge, int[] Edge_value) {
    // 创建每个节点
    for (int i = 0; i < n; i++) {
      graph.put(i, new ArrayList<int[]>());
    }
    // 构造图
    for (int i = 0; i < n-1; i++) {
      //将树边视为双向的
      graph.get(Tree_edge[i].start)
        .add(new int[]{Tree_edge[i].end, Edge_value[i]});
      graph.get(Tree_edge[i].end)
        .add(new int[]{Tree_edge[i].start, Edge_value[i]});
    }
    // 因为边是双向的,随便从哪个节点开始dfs都一样。这里用了node-0。
    // -1 作为parent
    dfs(0, -1);
    return globalMax;
  }
  
  // returns the max cost path-to-leaf from this root.
  int dfs(int root, int parent) {
    int maxCost = 0;
    int maxCost2 = 0;
    
    for (int[] neiCost : graph.get(root)) {
      // 注:BaseCase(即leaf)只有1个nei,即父级
      //       因此,leaf将直接返回maxCost=0。
      if (neiCost[0] == parent) continue;   // don't revisit parent
      
      //递归查找任何叶的最大成本路径
      int cost = dfs(neiCost[0], root) + neiCost[1];
      // keep 2 largest cost
      if (cost >= maxCost) {
        maxCost2 = maxCost;
        maxCost = cost;
      } else if (cost >= maxCost2) {
        maxCost2 = cost;
      }
    }
    // 检查2条最大路径是否为全局最大路径
    globalMax = Math.max(
      globalMax,
      maxCost + maxCost2
    );

    return maxCost;
  }
}

90.最大数

给定一个长度为n的数组nums,数组由一些非负整数组成,现需要将他们进行排列并拼接,每个数不可拆分,使得最后的结果最大,返回值需要是string类型,否则可能会溢出。
在这里插入图片描述

import java.util.*;


public class Solution {
    public String solve (int[] nums) {
        String[] strs = new String[nums.length];
        for(int i=0;i<nums.length;i++)
            strs[i] = String.valueOf(nums[i]);
        Arrays.sort(strs,new Comparator<String>(){
            @Override
            public int compare(String n1,String n2){
                String s1 = n1+n2;
                String s2 = n2+n1;
                return s2.compareTo(s1);
            } 
        });
        String res = "";
        for(String s:strs)
            res += s;
        if(res.charAt(0)=='0' && res.length()>1) return "0";
        return res;
        
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值