面试题41:数据流中的中位数
int i = 0;
//遍历找到插入点
for(i; i < val.size(); i++){
if(num <= val.get(i))
break;
}
//插入相应位置
val.add(i, num);
import java.util.*;
public class Solution {
private ArrayList<Integer> val = new ArrayList<Integer>();
public void Insert(Integer num) {
if(val.isEmpty())
//val中没有数据,直接加入
val.add(num);
//val中有数据,需要插入排序
else{
int i = 0;
//遍历找到插入点
for(i; i < val.size(); i++){
if(num <= val.get(i))
break;
}
//插入相应位置
val.add(i, num);
}
}
public Double GetMedian() {
int n = val.size();
//奇数个数字
if(n % 2 == 1)
//类型转换
return (double)val.get(n / 2);
//偶数个数字
else{
double a = val.get(n / 2);
double b = val.get(n / 2 - 1);
return (a + b) / 2;
}
}
}
堆排序时间复杂度 O(Nlog2N)
import java.util.*;
public class Solution {
//小顶堆,元素数值都比大顶堆大
private PriorityQueue<Integer> max = new PriorityQueue<>();
//大顶堆,元素数值较小
private PriorityQueue<Integer> min = new PriorityQueue<>((o1, o2)->o2.compareTo(o1));
//维护两个堆,取两个堆顶部即与中位数相关
public void Insert(Integer num) {
//先加入较小部分
min.offer(num);
//将较小部分的最大值取出,送入到较大部分
max.offer(min.poll());
//平衡两个堆的数量
if(min.size() < max.size())
min.offer(max.poll());
}
public Double GetMedian() {
//奇数个
if(min.size() > max.size())
return (double)min.peek();
else
//偶数个
return (double)(min.peek() + max.peek()) / 2;
}
}
面试题42:连续子数组的最大和
import java.util.*;
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
//记录到下标i为止的最大连续子数组和
int[] dp = new int[array.length];
dp[0] = array[0];
int maxsum = dp[0];
for(int i = 1; i < array.length; i++){
//状态转移:连续子数组和最大值
dp[i] = Math.max(dp[i - 1] + array[i], array[i]);
//维护最大值
maxsum = Math.max(maxsum, dp[i]);
}
return maxsum;
}
}
import java.util.*;
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
int x = array[0];
int y = 0;
int maxsum = x;
for(int i = 1; i < array.length; i++){
//状态转移:连续子数组和最大值
y = Math.max(x + array[i], array[i]);
//维护最大值
maxsum = Math.max(maxsum, y);
//更新x的状态
x = y;
}
return maxsum;
}
}
面试题43:1~n整数中1出现的次数
import java.util.*;
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int res = 0;
//MulBase = 10^i
long MulBase = 1;
//每位数按照公式计算
for(int i = 0; MulBase <= n; i++){
//根据公式添加
res += (n / (MulBase * 10)) * MulBase +
Math.min(Math.max(n % (MulBase * 10) - MulBase + 1, (long)0), MulBase);
//扩大一位数
MulBase *= 10;
}
return res;
}
}
import java.util.*;
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int res = 0;
//遍历1-n
for(int i = 1; i <= n; i++){
//遍历每个数的每一位
for(int j = i; j > 0; j = j / 10){
//遇到数字1计数
if(j % 10 == 1)
res++;
}
}
return res;
}
}
面试题44:数字序列中某一位的数字
//最开始想的两种方法
//题目理解错了
//1.char charAt(int index) 方法:得到指定位置的字符
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型
* @return int整型
*/
public int findNthDigit (int n, String str) {
// write code here
return (int)str.charAt(n - 1) - (int)"0";
}
}
//2.字符串转化成字符串数组,然后按索引取值转换
char类型转换成int类型:
方法一:
第一种利用Integer包装类的方法Integer.parseInt;
char ch = '9';
if (Character.isDigit(ch)){ // 判断是否是数字
int num = Integer.parseInt(String.valueOf(ch));
System.out.println(num);
}
方法二:
第二种方法利用字符强制转化为int型时,转化为ASCII码的特点。其字符的ASCII码值减去0的ASCII码值等于数值本身
char ch = '9';
if (Character.isDigit(ch)){ // 判断是否是数字
int num = (int)ch - (int)('0');
System.out.println(num);
}
import java.util.*;
public class Solution {
public int findNthDigit (int n) {
//记录n是几位数
int digit = 1;
//记录当前位数区间的起始数字:1,10,100...
long start = 1;
//记录当前区间之前总共有多少位数字
long sum = 9;
//将n定位在某个位数的区间中
while(n > sum){
n -= sum;
start *= 10;
digit++;
//该区间的总共位数
sum = 9 * start * digit;
}
//定位n在哪个数字上
String num = "" + (start + (n - 1) / digit);
//定位n在数字的哪一位上
int index = (n - 1) % digit;
return (int)(num.charAt(index)) - (int)('0');
}
}
import java.util.*;
public class Solution {
public int findNthDigit (int n) {
//记录n是几位数
int i = 1;
while(i * Math.pow(10, i) < n){
//前面添0增加的位
n += Math.pow(10, i);
i++;
}
String num = "" + (n / i);
//根据除法锁定目标数字,根据取模锁定位置
return (int)(num.charAt(n % i)) - (int)('0');
}
}
面试题45:把数组排成最小的数
bool cmp(string& x, string& y){
//叠加
return x + y < y + x;
}
import java.util.*;
public class Solution {
public String PrintMinNumber(int [] numbers) {
//空数组的情况
if(numbers == null || numbers.length == 0)
return "";
String[] nums = new String[numbers.length];
//将数字转成字符
for(int i = 0; i < numbers.length; i++)
nums[i] = numbers[i] + "";
//按照重载排序
Arrays.sort(nums, new Comparator<String>() {
public int compare(String s1, String s2) {
return (s1 + s2).compareTo(s2 + s1);
}
});
StringBuilder res = new StringBuilder();
//字符串叠加
for(int i = 0; i < nums.length; i++)
res.append(nums[i]);
return res.toString();
}
}
JAVA 数组转字符串
在数组类中并没有对此方法重写(override),仅仅是重载(overload)为类的静态方法。
所以数组转为字符串应写成:Arrays.toString(a)
数组转字符串一般而言有三种方法:
一、遍历String[] arr = { "0", "1", "2", "3", "4", "5" };// 遍历
StringBuffer str5 = new StringBuffer();for (String s : arr) {
str5.append(s);
}
System.out.println(str5.toString()); // 012345
二、使用StringUtils的join方法//数组转字符串 org.apache.commons.lang3.StringUtils
String str3 = StringUtils.join(arr); // 数组转字符串,其实使用的也是遍历
System.out.println(str3); // 012345
String str4 = StringUtils.join(arr, ","); // 数组转字符串(逗号分隔)(推荐)
System.out.println(str4); // 0,1,2,3,4,5
三、使用ArrayUtils的toString方法// 数组转字符串 org.apache.commons.lang3.ArrayUtils
String str2 = ArrayUtils.toString(arr, ","); // 数组转字符串(逗号分隔,首尾加大括号)
System.out.println(str2); // {0,1,2,3,4,5}
import java.util.*;
public class Solution {
public String PrintMinNumber(int [] numbers) {
//空数组的情况
if(numbers == null || numbers.length == 0)
return "";
String[] nums = new String[numbers.length];
//将数字转成字符
for(int i = 0; i < numbers.length; i++)
nums[i] = numbers[i] + "";
//冒泡排序
for(int i = 0; i < nums.length - 1; i++){
for(int j = 0; j < nums.length - i - 1; j++){
String s1 = nums[j] + nums[j + 1];
String s2 = nums[j + 1] + nums[j];
//比较拼接的大小交换位置
if(s1.compareTo(s2) > 0){
String temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
StringBuilder res = new StringBuilder();
//字符串叠加
for(int i = 0; i < nums.length; i++)
res.append(nums[i]);
return res.toString();
}
}
面试题46:把数字翻译成字符串
import java.util.*;
public class Solution {
/**
* 解码
* @param nums string字符串 数字串
* @return int整型
*/
public int solve (String nums) {
// write code here
//排除0
if(nums.equals("0"))
return 0;
//排除只有一种可能的10 和 20
if(nums == "10" || nums == "20")
return 1;
//当0的前面不是1或2时,无法译码,0种
for(int i = 1; i < nums.length(); i++){
if(nums.charAt(i) == '0')
if(nums.charAt(i - 1) != '1' && nums.charAt(i - 1) != '2')
return 0;
}
int[] dp = new int[nums.length() + 1];
//辅助数组初始化为1
//辅助数组全部用1填充
Arrays.fill(dp, 1);
for(int i = 2; i <= nums.length(); i++){
//在11-19,21-26之间的情况
if((nums.charAt(i - 2) == '1' && nums.charAt(i - 1) != '0')
|| (nums.charAt(i - 2) == '2' && nums.charAt(i - 1) > '0'
&& nums.charAt(i - 1) < '7'))
dp[i] = dp[i - 1] + dp[i - 2];
else
dp[i] = dp[i - 1];
}
return dp[nums.length()];
}
}
public class Solution {
public int solve (String nums) {
return back(nums.toCharArray(), 0);
}
// 递归函数
public int back(char[] nums, int start){
//当start走到终点时,证明已经解码完毕,直接返回1
if(start == nums.length){
return 1;
}
//当字符为0的时候,0没对应的解码,所以直接返回0 (此路解码废掉)
if(nums[start] == '0')
return 0;
//每次解码一个字符
int res1 = back(nums,start+1);
int res2 = 0;
//如果当前字符等于1 或者 当前字符加上下一个字符合起来小于等于26 则可以一次解码两个字符
if((start < nums.length-1)
&& (nums[start] == '1' || (nums[start] == '2' &&nums[start+1] <= '6'))){
res2 = back(nums,start+2);
}
//返回结果
return res1 + res2;
}
}
面试题47:礼物的最大价值
import java.util.*;
public class Solution {
public int maxValue (int[][] grid) {
int m = grid.length;
int n = grid[0].length;
//第一列只能来自上方
for(int i = 1; i < m; i++)
grid[i][0] += grid[i - 1][0];
//第一行只能来自左边
for(int i = 1; i < n; i++)
grid[0][i] += grid[0][i - 1];
//遍历后续每一个位置
for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
//增加来自左边的与上边的之间的较大值
grid[i][j] += Math.max(grid[i - 1][j], grid[i][j - 1]);
return grid[m - 1][n - 1];
}
}
import java.util.*;
public class Solution {
private int recursion(int[][] grid, int m, int n, int[][] dp){
//到达起点,停止递归
if(m == 0 && n == 0){
dp[0][0] = grid[0][0];
return grid[0][0];
}
//两个边界
if(m == 0)
dp[0][n] = grid[0][n] + recursion(grid, m, n - 1, dp);
if(n == 0)
dp[m][0] = grid[m][0] + recursion(grid, m - 1, n, dp);
//如果有值可以直接返回
if(dp[m][n] == 0)
//递归求左边或者上边的最大值
dp[m][n] = grid[m][n] +
Math.max(recursion(grid, m - 1, n, dp), recursion(grid, m, n - 1, dp));
return dp[m][n];
}
public int maxValue (int[][] grid) {
int m = grid.length;
int n = grid[0].length;
//用于记忆递归过程中的值
int[][] dp = new int[m][n];
return recursion(grid, m - 1, n - 1, dp);
}
}
面试题48:最长不含重复字符的子字符串
while(mp.get(s.charAt(right)) > 1)
//窗口左移,同时减去该数字的出现次数
mp.put(s.charAt(left), mp.get(s.charAt(left++)) - 1);
import java.util.*;
public class Solution {
public int lengthOfLongestSubstring (String s) {
//哈希表记录窗口内非重复的字符
HashMap<Character, Integer> mp = new HashMap<>();
int res = 0;
//设置窗口左右边界
for (int left = 0, right = 0; right < s.length(); right++) {
//窗口右移进入哈希表统计出现次数
if (mp.containsKey(s.charAt(right)))
mp.put(s.charAt(right), mp.get(s.charAt(right)) + 1);
else
mp.put(s.charAt(right), 1);
//出现次数大于1,则窗口内有重复
while (mp.get(s.charAt(right)) > 1)
//窗口左移,同时减去该字符的出现次数
mp.put(s.charAt(left), mp.get(s.charAt(left++)) - 1);
//维护子串长度最大值
res = Math.max(res, right - left + 1);
}
return res;
}
}
import java.util.*;
public class Solution {
public int lengthOfLongestSubstring (String s) {
//哈希表记录窗口内非重复的字符及其下标
HashMap<Character, Integer> mp = new HashMap<>();
int res = 0;
//dp[i]表示以下标i结尾的字符串最长不含重复子串的长度
int[] dp = new int[s.length() + 1];
for (int i = 1; i <= s.length(); i++) {
dp[i] = 1;
//哈希表中没有,说明不重复
if (!mp.containsKey(s.charAt(i - 1)))
//前一个加1
dp[i] = dp[i - 1] + 1;
//遇到重复字符
else
dp[i] = Math.min(dp[i - 1] + 1, i - mp.get(s.charAt(i - 1)));
//加入哈希表
mp.put(s.charAt(i - 1), i);
//维护最大值
res = Math.max(res, dp[i]);
}
return res;
}
}
面试题49:丑数
public int GetUglyNumber_Solution(int index) {
//1 2 3 4 5 6 8
if (index <= 6)
return index; // 加快程序输出
// 三个变量 后面有大作用!
int i2 = 0, i3 = 0, i5 = 0;
int[] res = new int[index];
res[0] = 1; // 第一个丑数为 1
for (int i = 1; i < index; i++) {
// 得到下一个丑数,三者中最小的
res[i] = Math.min(res[i2] * 2, Math.min(res[i3] * 3, res[i5] * 5));
/*第一次是 2、3、5比较,得到最小的是2*/
/*第二次是 4、3、5比较,为什么是4了呢?
因为上次2已经乘了一次了,所以接下去可以放的丑数在4、3、5之间*/
// 所以开头的三个指针就是来标记2 3 5 乘的次数的
if (res[i] == res[i2] * 2)
i2++;
if (res[i] == res[i3] * 3)
i3++;
if (res[i] == res[i5] * 5)
i5++;
}
return res[index - 1];
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
System.out.println( getNumber(50));
long end = System.currentTimeMillis();
System.out.println(end - start);
}
private static int getNumber(int n){
int x= 1;
int i= 0;
while (true){
if(isNeedNum(x)){
i++;
if(i==n){
return x;
}
}
x++;
}
}
private static boolean isNeedNum(int j){
int x= j;
while (x%2==0){
x=x/2;
}
while (x%3==0){
x=x/3;
}
while (x%5==0){
x=x/5;
}
if(x==1){
return true;
}
return false;
}
面试题50:第一个只出现一次的字符
import java.util.*;
public class Solution {
public int FirstNotRepeatingChar(String str) {
//异常检测
if(str == null || str.length() == ){
return -1;
}
HashMap<Character, Integer> mp = new HashMap<>();
//统计每个字符出现的次数
for(int i = 0; i < str.length(); i++)
//getOrDefault()
//获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
mp.put(str.charAt(i), mp.getOrDefault(str.charAt(i), 0) + 1);
//找到第一个只出现一次的字母
for(int i = 0; i < str.length(); i++)
if(mp.get(str.charAt(i)) == 1)
return i;
//没有找到
return -1;
}
}
//位置置为-1
mp[str[i]] = -1;
while(!q.empty() && mp[q.front().first] == -1)
q.pop();
import java.util.*;
public class Solution {
public int FirstNotRepeatingChar(String str) {
//统计字符出现的位置
HashMap<Character, Integer> mp = new HashMap<>();
Queue<Character> q1 = new LinkedList<>();
Queue<Integer> q2 = new LinkedList<>();
for(int i = 0; i < str.length(); i++){
//没有出现过的字符
if(!mp.containsKey(str.charAt(i))){
mp.put(str.charAt(i), i);
q1.offer(str.charAt(i));
q2.offer(i);
//找到重复的字符
}else{
//位置置为-1
mp.put(str.charAt(i), -1);
//弹出前面所有的重复过的字符
while(!q1.isEmpty() && mp.get(q1.peek()) == -1){
q1.poll();
q2.poll();
}
}
}
return q2.isEmpty() ? -1 : q2.poll();
}
}
//题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从
//字符流中只读出前两个字符"go"时,第一个只出现一次的字符是'g'。当从该字
//符流中读出前六个字符"google"时,第一个只出现一次的字符是'l'。
public class FirstCharacterInStream {
private int index;
private int[] occurence;
public FirstCharacterInStream() { //在构造函数中初始化成员变量
index=0;
occurence = new int[256];
for(int i=0;i<256;i++) {
//哈希表的值都初始化为1
occurence[i]=-1;
}
}
public void insert(char ch) {
if(occurence[(int)ch]==-1) {
occurence[(int)ch]=index; //第一次出现
}else if(occurence[(int)ch]>=0) {
occurence[(int)ch]=-2; //已经出现过了
}
index++;
}
public char getFirst() {
int minIndex=Integer.MAX_VALUE; //最大的integer
//# ascii 值 35
char ch='#';
for(int i=0;i<256;i++) {
if(occurence[i]>=0 && occurence[i]<minIndex) {
ch = (char) i;
minIndex=occurence[i];
}
}
return ch;
}
}
public static void main(String[] args) {
//字符转化为ASCII码
char ch_a = 'a';
int code_a = (int)ch_a; // =ASCII码97
//ASCII码转化为字符
char copyCh_a = (char) code_a; // =ASCII码97对应的字符'a'
//字符形式数字转化为整型
char c1 = '2';
int n1 = c1-'0'; //=2, 由'2'和'1'的ASCII码相减得到
//数字转化为字符形式
char copyC1 = (char)(n1+'0'); //='2' ,由'0'的ASCII码加2得到'2'的ASCII码
System.out.println(5);
}