LeetCode 1711. 大餐计数/NC59 矩阵的最小路径和/NC19 子数组的最大累加和问题/NC4 判断链表中是否有环/NC34 求路径/NC65大数斐波那契数列/NC76用两个栈实现队列(
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1711. 大餐计数/NC59 矩阵的最小路径和/NC19 子数组的最大累加和问题/NC4 判断链表中是否有环/NC34 求路径/NC65大数斐波那契数列/NC76用两个栈实现队列(相关的知识,希望对你有一定的参考价值。
1711. 大餐计数
2021.7.7 每日一题
题目描述
大餐 是指 恰好包含两道不同餐品 的一餐,其美味程度之和等于 2 的幂。
你可以搭配 任意 两道餐品做一顿大餐。
给你一个整数数组 deliciousness ,其中 deliciousness[i] 是第 i 道餐品的美味程度,返回你可以用数组中的餐品做出的不同 大餐 的数量。结果需要对 109 + 7 取余。
注意,只要餐品下标不同,就可以认为是不同的餐品,即便它们的美味程度相同。
示例 1:
输入:deliciousness = [1,3,5,7,9]
输出:4
解释:大餐的美味程度组合为 (1,3) 、(1,7) 、(3,5) 和 (7,9) 。
它们各自的美味程度之和分别为 4 、8 、8 和 16 ,都是 2 的幂。
示例 2:
输入:deliciousness = [1,1,1,3,3,3,7]
输出:15
解释:大餐的美味程度组合为 3 种 (1,1) ,9 种 (1,3) ,和 3 种 (1,7) 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-good-meals
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
一看就是典型的竞赛题,和两数之和差不多
class Solution {
public static final int REMAINDER = 1000000007;
public int countPairs(int[] deliciousness) {
//典型竞赛题
//哈希表
int res = 0;
Map<Integer, Integer> map = new HashMap<>();
int l = deliciousness.length;
for(int i = 0; i < l; i++){
int curr = deliciousness[i];
for(int j = 0; j < 27; j++){
int bit = (1 << j);
if(map.containsKey(bit - curr))
res = (res + map.get(bit - curr)) % REMAINDER;
}
map.put(curr, map.getOrDefault(curr, 0) + 1);
}
return res;
}
}
NC59 矩阵的最小路径和
题目描述
给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。
示例1
输入:
[[1,3,5,9],[8,1,3,4],[5,0,6,1],[8,8,4,0]]
返回值:
12
思路
因为只能从左边或者上边到达当前位置,直接动规,需要注意的是,因为我这里创建dp数组的时候,多加了一维,如果不对其进行初始化,会造成不适从左上角开始走的。所以需要对这里进行初始化,使得保证从第一个位置开始出发。
import java.util.*;
public class Solution {
/**
*
* @param matrix int整型二维数组 the matrix
* @return int整型
*/
public int minPathSum (int[][] matrix) {
// write code here
//动规
int m = matrix.length;
int n = matrix[0].length;
int[][] dp = new int[m + 1][n + 1];
Arrays.fill(dp[0], Integer.MAX_VALUE);
for(int i = 1; i <= m; i++){
dp[i][0] = Integer.MAX_VALUE;
}
dp[0][1] = 0;
dp[1][0] = 0;
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + matrix[i - 1][j - 1];
}
}
return dp[m][n];
}
}
NC19 子数组的最大累加和问题
题目描述
给定一个数组arr,返回子数组的最大累加和
例如,arr = [1, -2, 3, 5, -2, 6, -1],所有子数组中,[3, 5, -2, 6]可以累加出最大的和12,所以返回12.
题目保证没有全为负数的数据
[要求]
时间复杂度为O(n)O(n),空间复杂度为O(1)O(1)
示例1
输入:
[1, -2, 3, 5, -2, 6, -1]
返回值:
12
思路
import java.util.*;
public class Solution {
/**
* max sum of the subarray
* @param arr int整型一维数组 the array
* @return int整型
*/
public int maxsumofSubarray (int[] arr) {
// write code here
//dp[i] = max(dp[i - 1] + arr[i] , arr[i])
int l = arr.length;
int max = arr[0];
for(int i = 1; i < l; i++){
arr[i] = Math.max(arr[i], arr[i] + arr[i - 1]);
max = Math.max(max, arr[i]);
}
return max;
}
}
NC4 判断链表中是否有环
题目描述
判断给定的链表中是否有环。如果有环则返回true,否则返回false。
你能给出空间复杂度O(1)的解法么?
输入分为2部分,第一部分为链表,第二部分代表是否有环,然后回组成head头结点传入到函数里面。-1代表无环,其他的数字代表有环,这些参数解释仅仅是为了方便读者自测调试
示例1
输入:
{3,2,0,-4},1
返回值:
true
说明:
第一部分{3,2,0,-4}代表一个链表,第二部分的1表示,-4到位置1,即-4->2存在一个链接,组成传入的head为一个带环的链表 ,返回true
示例2
输入:
{1},-1
返回值:
false
说明:
第一部分{1}代表一个链表,-1代表无环,组成传入head为一个无环的单链表,返回false
示例3
输入:
{-1,-7,7,-4,19,6,-9,-5,-2,-5},6
返回值:
true
思路
快慢指针
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
//快慢指针
if(head == null)
return false;
ListNode slow = head;
ListNode fast = head.next;
while(slow != fast){
if(fast == null || fast.next == null)
return false;
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
NC34 求路径
题目描述
一个机器人在m×n大小的地图的左上角(起点)。
机器人每次向下或向右移动。机器人要到达地图的右下角(终点)。
可以有多少种不同的路径从起点走到终点?
备注:m和n小于等于100,并保证计算结果在int范围内
思路
刚开始想用数学的方法,相当于能走m+n步,然后找m步或者n步的位置。相当于求一个组合数
直接化简以后求阶乘的值,代码如下:
import java.util.*;
public class Solution {
/**
*
* @param m int整型
* @param n int整型
* @return int整型
*/
public int uniquePaths (int m, int n) {
// write code here
//求组合数
int A = m + n - 2;
int B = n - 1;
double t = 1.0;
for(int i = 1; i <= B; i++){
t = t * (A - B + i) / i;
}
return (int)t;
}
}
还是乖乖动规
import java.util.*;
public class Solution {
/**
*
* @param m int整型
* @param n int整型
* @return int整型
*/
public int uniquePaths (int m, int n) {
// write code here
//动态规划可以
//写个一维的
int[] dp = new int[n];
Arrays.fill(dp, 1);
for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
dp[j] = dp[j] + dp[j - 1];
}
}
return dp[n - 1];
}
}
NC68 跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
思路
最简单的动规
public class Solution {
public int jumpFloor(int target) {
int pre = 1; //跳0层
int cur = 1; //跳1层
for(int i = 2; i <= target; i++){
int temp = cur + pre;
pre = cur;
cur = temp;
}
return cur;
}
}
NC112 进制转换
题目描述
给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数
思路
进制转换,短除法,注意测试用例里还有负数
import java.util.*;
public class Solution {
/**
* 进制转换
* @param M int整型 给定整数
* @param N int整型 转换到的进制
* @return string字符串
*/
public String solve (int M, int N) {
// write code here
boolean flag = true;
if(M < 0){
M = -M;
flag = false;
}
StringBuffer sb = new StringBuffer();
while(M != 0){
int remainer = M % N;
M = M / N;
if(remainer > 9){
sb.append((char)(remainer - 10 + 'A'));
}else
sb.append(remainer + "");
}
sb = sb.reverse();
if(!flag){
sb.insert(0, "-");
}
return sb.toString();
}
}
NC65 斐波那契数列
题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n≤39
思路
public class Solution {
public int Fibonacci(int n) {
if(n == 0)
return 0;
int pre = 0;
int cur = 1;
for(int i = 2; i <= n; i++){
int temp = cur + pre;
pre = cur;
cur = temp;
}
return cur;
}
}
如果是大数的斐波那契数列的话,一般题目会给对一个值取模,关于取模的操作如下,需要记一下:
可以采用矩阵快速幂的方法来对解法进行优化
首先,斐波那契数列写成矩阵的形式如下:
然后主要是求矩阵的n次方,这个怎么实现呢,可以用矩阵快速幂的方法
所以计算矩阵的n次方也可以用快速幂的方法
先定义矩阵的乘法。
然后求矩阵的n次幂,定义base初始矩阵,每次base都与自己相乘来更新base
将n与1相与,如果当前位为1,那么就加上当前的base
最后可以得到矩阵n次幂的结果,然后根据所求的序列用矩阵中的值来计算最后的结果
NC76用两个栈实现队列
题目描述
用两个栈来实现一个队列,分别完成在队列尾部插入整数(push)和在队列头部删除整数(pop)的功能。 队列中的元素为int类型。保证操作合法,即保证pop操作时队列内已有元素。
示例:
输入:
["PSH1","PSH2","POP","POP"]
返回:
1,2
解析:
"PSH1":代表将1插入队列尾部
"PSH2":代表将2插入队列尾部
"POP“:代表删除一个元素,先进先出=>返回1
"POP“:代表删除一个元素,先进先出=>返回2
思路
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(!stack2.isEmpty())
return stack2.pop();
else{
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
return stack2.pop();
}
}
}
以上是关于LeetCode 1711. 大餐计数/NC59 矩阵的最小路径和/NC19 子数组的最大累加和问题/NC4 判断链表中是否有环/NC34 求路径/NC65大数斐波那契数列/NC76用两个栈实现队列(的主要内容,如果未能解决你的问题,请参考以下文章