LeetCode数学问题

面试02.05 链表求和(string和int转换加)

题目

分析

1. 先使用stringbuilder对象将两个链表按序加(其实是反的)
2. 通过自己写的函数翻过去就是原来的数字(调正)
3. 相加之后拆开(一个数字拆成链表形式)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class LianBiaoHe {
public static void main(String[] args) {
ListNode l11=new ListNode(7); //添加7->1->6
ListNode l12=new ListNode(1);
ListNode l13=new ListNode(6);
l11.next=l12;
l12.next=l13;

ListNode l21=new ListNode(5); //添加5->9->2
ListNode l22=new ListNode(9);
ListNode l23=new ListNode(2);
l21.next=l22;
l22.next=l23;
System.out.println(addTwoNumbers(l11,l21));
}

public static int addTwoNumbers(ListNode l1, ListNode l2) {
int sum=0;
StringBuilder sb1=new StringBuilder();
StringBuilder sb2=new StringBuilder();
int flag=0; //记录有几个节点
while(l1!=null){
sb1.append(l1.val);
l1=l1.next;
flag++; //记录有几个节点
}
while(l2!=null){
sb2.append(l2.val);
l2=l2.next;
}
int a=fanzhuan(Integer.parseInt(String.valueOf(sb1)));
int b=fanzhuan(Integer.parseInt(String.valueOf(sb2)));
System.out.println(a+" "+b);
return a+b;
}


//自定义数字反转函数 617->716
public static int fanzhuan(int n){
StringBuilder sb3=new StringBuilder();
int m=1;
while (n!=0){
sb3.append(n%10);
n=n/10;
}
return Integer.parseInt(String.valueOf(sb3)); //字符串转int正数
}

}

结果


面试16.01 交换数字(中间值/数组交换)

题目

分析

1. 使用temp中间值(循环给)
        temp=a;  //a的值给temp
        a=b;     //b的值给a(a已经给temp)
        b=temp;  //temp的值给b(b已经给a)

2. 不适用temp中间值
        数组交换

代码

1
2
3
4
5
6
7
8
class Solution {
public int[] swapNumbers(int[] numbers) {
int[] a=new int[2];
a[0]=numbers[1]; //原来第二个数到第一个
a[1]=numbers[0]; //原来第一个数到第二个
return a;
}
}

结果


面试16.05 阶乘尾数(大数乘法/5的因数)

题目

分析

1. 先计算出阶乘的值 然后按位输出判断0的个数
2. 判断5的因数个数(多少个数字能整除5)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class JieChengWeiShu {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt();
System.out.println(trailingZeroes(n));
}

public static int trailingZeroes(int n) {
int ans=0;
while(n>0){
ans+=n/5; //不断的/5求次数
n/=5;
}
return ans;
}

}

结果


面试17.06 2出现的次数(取每位值)

题目

分析

1.思路:通过每一个数循环去拆开这个数得到2的个数最后综合结果

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ErCiShu {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt();
int jie=0;
for(int i=1;i<=n;i++){ //从1到n都调用方法得到结果
jie+=numberOf2sInRange(i);
}
System.out.println(jie);
}

public static int numberOf2sInRange(int n) {
int ci=0; //记录2的个数
int m=1;
while (n != 0) {
m = n % 10;
if (m == 2) {
ci++; //每一位是2就ci++计数
}
n = n / 10;
}
return ci;
}

}

结果


面试17.09 第K个数(看是加3/5/7哪个)

题目

分析

以1 3 5 7 9序列为例:
    1. 第一轮找i=1下标 dp[1]=min(dp[0]*3,dp[0]*5,dp[0]*7)最后选3 p3指针后移到1
    2. 第二轮找i=2下标 dp[2]=min(dp[1]*3,dp[0]*5,dp[0]*7)最后选5 p5指针后移到1

注:其实就是不断地加3/5/7 看到底加哪个最近最好依次上升 

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class DiKShu {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt();
System.out.println(getKthMagicNumber(n));
}

public static int getKthMagicNumber(int k) {
int p3=0,p5=0,p7=0;
int[] dp=new int[k];
dp[0]=1; //第一个数一定是1
for(int i=1;i<k;i++){
dp[i]=Math.min(dp[p3]*3,Math.min(dp[p5]*5,dp[p7]*7)); //当前值肯定是离上一个最近的(找最小的)
//匹配到是哪一个就将对应指针后移 方便后面计算该多少个3/5/7
if(dp[i]==dp[p3]*3){
p3++;
}
if(dp[i]==dp[p5]*5) {
p5++;
}
if(dp[i]==dp[p7]*7) {
p7++;
}
}
return dp[k-1]; //返回数组最后一位
}

}

结果


面试14-I 剪绳子/整数拆分(分情况讨论)

题目

分析

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class JianShengZi {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt();
System.out.println(cuttingRope(n));
}

public static int cuttingRope(int n) {
if(n <= 3) {
return n - 1; //必须剪出一段长度为1的绳子
}
int a=n/3;
int b=n%3; //n=3a*b
if(b==0){
return (int)Math.pow(3, a); //3的a次方
}
if(b==1){
return (int)Math.pow(3, a - 1) * 4;
}
return (int)Math.pow(3, a) * 2; // 3 3 5(45) <<< 3 4 4(3*4*4=48)
}

}

结果


面试14-II 剪绳子(分情况讨论)

题目

分析

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public int cuttingRope(int n) {
if(n <= 3) return n - 1;
int b = n % 3, p = 1000000007;
long rem = 1, x = 3;
for(int a = n / 3 - 1; a > 0; a /= 2) {
if(a % 2 == 1) rem = (rem * x) % p;
x = (x * x) % p;
}
if(b == 0) return (int)(rem * 3 % p);
if(b == 1) return (int)(rem * 4 % p);
return (int)(rem * 6 % p);
}
}

结果


面试17.打印从1到最大的n位数(StringBuilder得最大值)

题目

分析

1. 通过StringBuilder对象获得最大值max
2. 通过Integer.parseInt(String.valueOf(sb))将字符串转整数
3. 最后通过循环将值导入数组输出数组

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface YiDaoN {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt();
System.out.println(Arrays.toString(printNumbers(n)));
}

public static int[] printNumbers(int n) {
StringBuilder sb=new StringBuilder();
while(n--!=0){
sb.append("9"); //不停地贴9
}
int max=Integer.parseInt(String.valueOf(sb)); //字符串转为整数int
int[] a=new int[max];
for(int i=0;i<max;i++){
a[i]=i+1;
}
return a;
}

}

结果


面试43 1-n整数中1出现的次数/数字1的个数(拆开求1个数)

题目

分析

和之前的求2的出现次数一样我每次每个数去拆开求解每一次出现1的次数即可

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Yi {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt();
int jie=0;
for(int i=1;i<=n;i++){ //从1到n都调用方法得到结果
jie+=numberOf2sInRange(i);
}
System.out.println(jie);
}

public static int numberOf2sInRange(int n) {
int ci=0; //记录1的个数
int m=1;
while (n != 0) {
m = n % 10;
if (m == 1) {
ci++; //每一位是1就ci++计数
}
n = n / 10;
}
return ci;
}

}

结果


面试44.数字序列中某一位的数字/第N个数

题目

分析

代码

1
2


结果


面试49.丑数(三指针分析)

题目

分析

1. 和只能包含3/5/7因子的题目一样
2. 指定p2 p3 p5三个指针只能进行乘对应数字,每次去判断最小的放入对应数组位置,然后将对应指针后移用于下轮判断

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class ChouShu {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt();
System.out.println(nthUglyNumber(n));
}

public static int nthUglyNumber(int n) {
int[] a=new int[n];
a[0]=1;
int p2=0;
int p3=0;
int p5=0;
for(int i=1;i<n;i++){
a[i]=Math.min(a[p2]*2,Math.min(a[p3]*3,a[p5]*5)); //就看哪个乘最小 放入当前位置
if(a[i]==a[p2]*2){
p2++; //哪个满足就要指针后移 为了下轮的判断
}
if(a[i]==a[p3]*3){
p3++;
}
if(a[i]==a[p5]*5){
p5++;
}
}

return a[n-1];
}

}

结果


素数(筛法)

题目

找到1-n之间的所有素数

分析

1. 定义一个布尔数组res(大小就是n+1)
2. 将所有值都先赋成true(后面不是的话要改为false)
3. 第一层循环从i=2到i=n/i遍历
4. 如果第一层的res[i]位置是true说明就是素数,找到对应的倍数改为false
5. 第二层循环从2 3 4这样的倍数去乘让对应位置变false

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n=input.nextInt(); //输入要判断的多大值
find(n); //调用方法返回结果
}

public static void find(int n){
boolean[] res=new boolean[n+1];
for(int i=0;i<res.length;i++){
res[i]=true;
}
for(int i=2;i<=n/i;i++){ //从2 3 4 5开始
if(res[i]){ //如果i这个位置是true说明是素数
for (int j=i;j<=n/i;j++) { //从i的1倍 2倍 3倍开始
res[i*j]=false;
}
}
}
for(int i=2;i<res.length;i++){ //从第二位开始输出 (0和1都不是素数)
if(res[i]){
System.out.print(i+" "); //输出素数
}
}
}

}

结果


16进制转10进制

分析

1. 将字符串转大写[toUpperCase()方法]之后分隔成字符数组[toCharArray()方法]
2. 倒序遍历这样方便计算每一次16的倍数[利用math的pow函数解决]
3. 判读就使用Character类的isDigit和isUpperCase判断是不是大写字母和数字,然后根据res=res原来的值+当前值*16的倍数
4. 最后结果是double需要转int即可

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String s=input.nextLine();
System.out.println(zhuan(s));
}

public static int zhuan(String s){
char[] c=s.toUpperCase().toCharArray(); //字符串全转为大写之后拆开 假设输入AbC --> [A,B,C]
double res=0; //最后接结果
int flag=0; //控制每次应该乘多少个16
for(int i=c.length-1;i>=0;i--){ //倒序方便利用flag计算当前位置是16的几次方
char temp=c[i]; //获取当前值
if(Character.isUpperCase(temp)){
if(temp>='A'&&temp<='F'){
res=(temp-'A'+10)*Math.pow(16.0,(double)(flag++))+res; //当前的字母对应的数字*16的倍数+之前的值
}else{
System.out.println("false!"); //出现的字符不在A-F之间
}
}else if(Character.isDigit(temp)){ //出现是0-9的范围内
res=res+(int)(temp-48)*Math.pow(16.0,(double)(flag++)); //当前的字母对应的数字*16的倍数+之前的值
}
}
return (int)res; //因为使用pow函数返回值是double 最后我们需要转为int
}

}

结果


10进制转16进制

分析

1. 就跟10进制转2进制一样
2. 不断地n/16拆分 每一个余数n%16就是结果集(但是要反序)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=input.nextInt(); //输入10进制
System.out.println(find(n));
}

public static String find(int n){
StringBuilder sb=new StringBuilder();
//就跟10进制转2进制一样(直到10进制的数字拆为0结束)
while(n!=0){
int temp=n%16; //获取每一次的余数(要拼接的数字 只不过要反序)
//是普通的0-9的数字
if(temp>=0&&temp<=9){
sb.append(temp); //直接填进去
}else if(temp>=10&&temp<=15){
sb.append((char)(temp-10+'a')); //是10-15的范围内 需要转为a-f
}
else{
System.out.println("false"); //不符合16进制的要求
break;
}
n=n/16; //不断将数字拆小
}
return sb.reverse().toString(); //倒序粘贴在一起才是最终答案
}

}

结果


旅行终点站(找某个路径的终点不是其他的起点)

题目

分析

1.思路: 如果某个路径的终点不是另一个路径的起点,则该点就是旅行终点.
2.实现: 
    2.1 使用map存储所有路径的出发点[path.get(0)]
    2.2 判断set里面没有哪个get(1)的值就说明是终点

代码

1
2
3
4
5
6
7
8
9
10
11
12
13

public String destCity(List<List<String>> paths) {
HashSet<String> set = new HashSet<>();
for (List<String> path : paths) {
set.add(path.get(0)); //所有出发点放入set
}
for (List<String> path : paths) {
if (!set.contains(path.get(1))) { //如果某个终点没有在出发点集合中 说明就是终点
return path.get(1); //返回终点即可
}
}
return null;
}

实现


汉明距离(异或性质/布赖恩·克尼根算法)

题目

分析

1. 其实就是两个数字变二进制,找二进制不同的两个位置之间距离
2. 使用异或的性质:相同为0不同为1
3. 执行步骤:
    1. 先将x和y异或之后的结果 只要找到这个结果出现1的位置就说明是两个数不同的位置
    2. 不断变小,不断判断%2是否为1记录距离

https://leetcode-cn.com/problems/hamming-distance/solution/yi-ming-ju-chi-by-leetcode/

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println(hammingDistance(1,4));
}

public static int hammingDistance(int x, int y) {
int xor = x ^ y; // 0001异或0100 --> 0101就是5
System.out.println("异或结果"+xor);
int distance = 0; //测量距离
while (xor != 0) {
if (xor % 2 == 1) //不同的话就是异或的结果为1的地方
distance += 1;
xor = xor /2; //变小
}
return distance; //返回距离
}

}

结果


增减字符串匹配(双指针移动)

题目

分析

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

public static int[] diStringMatch(String s) {
int n=s.length(); //获取字符串长度n
int[] res=new int[n+1]; //结果长为n+1
//确定左右指针
int left=0;
int right=n;
for (int i = 0; i < n; i++) {
char temp = s.charAt(i); //获取字符串当前字符
if (temp == 'I') { //递增
res[i]=left++;
}
if (temp == 'D') { //递减
res[i]=right--;
}
}
res[n]=left; //最后一个n+1的位置没有判断 添加left进去
return res;
}

结果


最长特殊序列I(判断字符串长度)

题目

分析

代码

1
2
3
4
5
6

public int findLUSlength(String a, String b) {
if (a.equals(b))
return -1; //如果两个字符串相同 返回-1
return Math.max(a.length(), b.length()); //如果不相同就看谁的更长度更长了
}

结果


非递增顺序的最小子序列(数学问题)

题目

分析

1. 其实就是找一段序列是大于总和/2的
2. 存的话就用list集合存
3. 先排序之后倒序遍历插入找即可

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

public List<Integer> minSubsequence(int[] nums) {
Arrays.sort(nums); //排序
int left=0; //左指针
int right=nums.length-1; //右指针
int sum=0, sum_right=0;
for(int i=0; i<nums.length; i++){
sum += nums[i]; //求总和sum
}
List<Integer> ans = new ArrayList<>(); //接住结果
while(sum_right <= sum/2){
ans.add(nums[right]);
sum_right += nums[right]; //倒序相加 超过总和的一半就弹出
left++;
right--;
}
return ans; //返回结果
}

结果


换酒问题(不断缩小)

题目

分析

1. 其实很像进制转换,不过需要考虑换完之后要加上换了的数量
2. 只要sum剩下的酒瓶 < 要兑换的酒瓶就弹出

代码

1
2
3
4
5
6
7
8
9
10
11
12
13

public int numWaterBottles(int sum, int numExchange) {
int total = sum; //首先将sum加入
while (sum >= numExchange) { //手里的酒瓶数 < 要兑换酒瓶数量
//change表示的是兑换成酒的数量
int change = sum / numExchange;
//total再加上兑换的酒
total += change;
//瓶子数量变为兑换成酒的数量加上没有兑换成酒的数量
sum = change + sum % numExchange; //更新手里的总数
}
return total;
}

结果


托普利茨矩阵(斜对角线数唯一)

题目

分析

1. 斜对角线hang-lie肯定是相同的,使用map存入第一个要判断的,然后对比后面的每一个hang-lie
2. 从1,1开始判断hang-1,lie-1的是否相同

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

//第一种 每一个斜对角线的hang-lie是相同的
// 将第一个hang-lie的元素存入map 后面判断错误返回false
public boolean isToeplitzMatrix(int[][] matrix) {
Map<Integer, Integer> groups = new HashMap();
for (int r = 0; r < matrix.length; ++r) {
for (int c = 0; c < matrix[0].length; ++c) {
if (!groups.containsKey(r-c))
groups.put(r-c, matrix[r][c]);
else if (groups.get(r-c) != matrix[r][c])
return false; //
}
}
return true;
}


//第二种 从(1,1)开始只是对照上一层的(i-1,j-1)元素
public boolean isToeplitzMatrix(int[][] matrix) {
int column = matrix[0].length;
for (int i = 1; i < matrix.length; i++) {
for (int j = 1; j < column; j++) {
if (matrix[i][j] != matrix[i - 1][j - 1])
return false; //如果不同就弹出false
}
}
return true;
}

结果


最小移动次数使数组元素相等

题目

分析

1. 每次使n-1个元素+1 == 每次使1个元素-1然后所有元素+1
2. 所以只需要找到:每次让1个元素-1,多少次后让所有元素相等

代码

1
2
3
4
5
6
7
8
9
10

public static int minMoves(int[] a) {
Arrays.sort(a); //对a数组进行排序
int res=0;
int count=a.length-1; //每次能够使n-1个元素增加1
for (int i = 0; i < a.length; i++) {
res+=a[i]-a[0]; //计算比a【0】多多少
}
return res;
}

结果


×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 面试02.05 链表求和(string和int转换加)
    1. 1.1. 题目
    2. 1.2. 分析
    3. 1.3. 代码
    4. 1.4. 结果
  2. 2. 面试16.01 交换数字(中间值/数组交换)
    1. 2.1. 题目
    2. 2.2. 分析
    3. 2.3. 代码
    4. 2.4. 结果
  3. 3. 面试16.05 阶乘尾数(大数乘法/5的因数)
    1. 3.1. 题目
    2. 3.2. 分析
    3. 3.3. 代码
    4. 3.4. 结果
  4. 4. 面试17.06 2出现的次数(取每位值)
    1. 4.1. 题目
    2. 4.2. 分析
    3. 4.3. 代码
    4. 4.4. 结果
  5. 5. 面试17.09 第K个数(看是加3/5/7哪个)
    1. 5.1. 题目
    2. 5.2. 分析
    3. 5.3. 代码
    4. 5.4. 结果
  6. 6. 面试14-I 剪绳子/整数拆分(分情况讨论)
    1. 6.1. 题目
    2. 6.2. 分析
    3. 6.3. 代码
    4. 6.4. 结果
  7. 7. 面试14-II 剪绳子(分情况讨论)
    1. 7.1. 题目
    2. 7.2. 分析
    3. 7.3. 代码
    4. 7.4. 结果
  8. 8. 面试17.打印从1到最大的n位数(StringBuilder得最大值)
    1. 8.1. 题目
    2. 8.2. 分析
    3. 8.3. 代码
    4. 8.4. 结果
  9. 9. 面试43 1-n整数中1出现的次数/数字1的个数(拆开求1个数)
    1. 9.1. 题目
    2. 9.2. 分析
    3. 9.3. 代码
    4. 9.4. 结果
  10. 10. 面试44.数字序列中某一位的数字/第N个数
    1. 10.1. 题目
    2. 10.2. 分析
    3. 10.3. 代码
    4. 10.4. 结果
  11. 11. 面试49.丑数(三指针分析)
    1. 11.1. 题目
    2. 11.2. 分析
    3. 11.3. 代码
    4. 11.4. 结果
  12. 12. 素数(筛法)
    1. 12.1. 题目
    2. 12.2. 分析
    3. 12.3. 代码
    4. 12.4. 结果
  13. 13. 16进制转10进制
    1. 13.1. 分析
    2. 13.2. 代码
    3. 13.3. 结果
  14. 14. 10进制转16进制
    1. 14.1. 分析
    2. 14.2. 代码
    3. 14.3. 结果
  15. 15. 旅行终点站(找某个路径的终点不是其他的起点)
    1. 15.1. 题目
    2. 15.2. 分析
    3. 15.3. 代码
    4. 15.4. 实现
  16. 16. 汉明距离(异或性质/布赖恩·克尼根算法)
    1. 16.1. 题目
    2. 16.2. 分析
    3. 16.3. 代码
    4. 16.4. 结果
  17. 17. 增减字符串匹配(双指针移动)
    1. 17.1. 题目
    2. 17.2. 分析
    3. 17.3. 代码
    4. 17.4. 结果
  18. 18. 最长特殊序列I(判断字符串长度)
    1. 18.1. 题目
    2. 18.2. 分析
    3. 18.3. 代码
    4. 18.4. 结果
  19. 19. 非递增顺序的最小子序列(数学问题)
    1. 19.1. 题目
    2. 19.2. 分析
    3. 19.3. 代码
    4. 19.4. 结果
  20. 20. 换酒问题(不断缩小)
    1. 20.1. 题目
    2. 20.2. 分析
    3. 20.3. 代码
    4. 20.4. 结果
  21. 21. 托普利茨矩阵(斜对角线数唯一)
    1. 21.1. 题目
    2. 21.2. 分析
    3. 21.3. 代码
    4. 21.4. 结果
  22. 22. 最小移动次数使数组元素相等
    1. 22.1. 题目
    2. 22.2. 分析
    3. 22.3. 代码
    4. 22.4. 结果
,