LeetCode 1716. 计算力扣银行的钱 / 382. 链表随机节点(蓄水池抽样) / 1220. 统计元音字母序列的数目(动规,矩阵快速幂)
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1716. 计算力扣银行的钱 / 382. 链表随机节点(蓄水池抽样) / 1220. 统计元音字母序列的数目(动规,矩阵快速幂)相关的知识,希望对你有一定的参考价值。
1716. 计算力扣银行的钱
2022.1.15 每日一题
题目描述
Hercy 想要为购买第一辆车存钱。他 每天 都往力扣银行里存钱。
最开始,他在周一的时候存入 1 块钱。从周二到周日,他每天都比前一天多存入 1 块钱。在接下来每一个周一,他都会比 前一个周一 多存入 1 块钱。
给你 n ,请你返回在第 n 天结束的时候他在力扣银行总共存了多少块钱。
示例 1:
输入:n = 4
输出:10
解释:第 4 天后,总额为 1 + 2 + 3 + 4 = 10 。
示例 2:
输入:n = 10
输出:37
解释:第 10 天后,总额为 (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4) = 37 。注意到第二个星期一,Hercy 存入 2 块钱。
示例 3:
输入:n = 20
输出:96
解释:第 20 天后,总额为 (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4 + 5 + 6 + 7 + 8) + (3 + 4 + 5 + 6 + 7 + 8) = 96 。
提示:
1 <= n <= 1000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/calculate-money-in-leetcode-bank
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
简单模拟
class Solution
public int totalMoney(int n)
int cycle = n / 7;
int mod = n % 7;
int base = (1 + 7) * 7 / 2;
int ans = 0;
for(int i = 0; i < cycle; i++)
ans += base;
base += 7;
for(int i = 0; i < mod; i++)
ans += cycle + i + 1;
return ans;
382. 链表随机节点
2022.1.16 每日一题
题目描述
给你一个单链表,随机选择链表的一个节点,并返回相应的节点值。每个节点 被选中的概率一样 。
实现 Solution 类:
Solution(ListNode head) 使用整数数组初始化对象。
int getRandom() 从链表中随机选择一个节点并返回该节点的值。链表中所有节点被选中的概率相等。
示例:
输入
[“Solution”, “getRandom”, “getRandom”, “getRandom”, “getRandom”, “getRandom”]
[[[1, 2, 3]], [], [], [], [], []]
输出
[null, 1, 3, 2, 2, 3]
解释
Solution solution = new Solution([1, 2, 3]);
solution.getRandom(); // 返回 1
solution.getRandom(); // 返回 3
solution.getRandom(); // 返回 2
solution.getRandom(); // 返回 2
solution.getRandom(); // 返回 3
// getRandom() 方法应随机返回 1、2、3中的一个,每个元素被返回的概率相等。
提示:
链表中的节点数在范围 [1, 10^4] 内
-10^4 <= Node.val <= 10^4
至多调用 getRandom 方法 10^4 次
进阶:
如果链表非常大且长度未知,该怎么处理?
你能否在不使用额外空间的情况下解决此问题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-random-node
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
因为只让返回值,就很简单了
/**
* Definition for singly-linked list.
* public class ListNode
* int val;
* ListNode next;
* ListNode()
* ListNode(int val) this.val = val;
* ListNode(int val, ListNode next) this.val = val; this.next = next;
*
*/
class Solution
//感觉吧,因为要使用整数数组初始化对象,所以挺简单的
//整数数组不算额外空间
//就把每个数组里存放一个当前结点的指针就可以了
int[] arr;
int len;
Random rd = new Random();
public Solution(ListNode head)
int idx = 0;
ListNode temp = head;
while(temp != null)
idx++;
temp = temp.next;
arr = new int[idx];
temp = head;
idx = 0;
while(temp != null)
arr[idx++] = temp.val;
temp = temp.next;
len = idx;
public int getRandom()
int t = rd.nextInt(len);
return arr[t];
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(head);
* int param_1 = obj.getRandom();
*/
还以为创建的数组不算额外空间呢,原来是要完全不使用任何空间
蓄水池抽样,从0到列表长度添加结点,每次加都会进行抽样,如果抽到0,那么就返回该结点
这样可以保证每个结点抽取到的概率都是1/n
水塘抽样由于空间小,时间复杂度低,可以用于大数据流中的随机抽样问题。
水塘抽样,适用于非常大的数据量,一般是流式的数据,你不知道大小有多少个,随机选取多个元素,这些被选取的元素放在一个池子中,随时有可能返回这个池子中的数。比如,在大数据领域,数据一直在处理,但是,在某个时间节点需要随机返回 5 个已经处理过的数据,我们就可以声明一个大小为 5 的池子来处理。
/**
* Definition for singly-linked list.
* public class ListNode
* int val;
* ListNode next;
* ListNode()
* ListNode(int val) this.val = val;
* ListNode(int val, ListNode next) this.val = val; this.next = next;
*
*/
class Solution
//传说中的蓄水池抽样
//如果抽不到就一直抽
//每次只有抽到0才返回当前结点
//每次抽取都需要遍历链表
ListNode head;
Random rd;
public Solution(ListNode head)
this.head = head;
rd = new Random();
public int getRandom()
int idx = 1;
int ans = 0;
ListNode temp = head;
while(temp != null)
if(rd.nextInt(idx) == 0)
ans = temp.val;
temp = temp.next;
idx++;
return ans;
/**
* Your Solution object will be instantiated and called as such:
* Solution obj = new Solution(head);
* int param_1 = obj.getRandom();
*/
1220. 统计元音字母序列的数目
2022.1.17 每日一题
题目描述
给你一个整数 n,请你帮忙统计一下我们可以按下述规则形成多少个长度为 n 的字符串:
字符串中的每个字符都应当是小写元音字母(‘a’, ‘e’, ‘i’, ‘o’, ‘u’)
每个元音 ‘a’ 后面都只能跟着 ‘e’
每个元音 ‘e’ 后面只能跟着 ‘a’ 或者是 ‘i’
每个元音 ‘i’ 后面 不能 再跟着另一个 ‘i’
每个元音 ‘o’ 后面只能跟着 ‘i’ 或者是 ‘u’
每个元音 ‘u’ 后面只能跟着 ‘a’
由于答案可能会很大,所以请你返回 模 10^9 + 7 之后的结果。
示例 1:
输入:n = 1
输出:5
解释:所有可能的字符串分别是:“a”, “e”, “i” , “o” 和 “u”。
示例 2:
输入:n = 2
输出:10
解释:所有可能的字符串分别是:“ae”, “ea”, “ei”, “ia”, “ie”, “io”, “iu”, “oi”, “ou” 和 “ua”。
示例 3:
输入:n = 5
输出:68
提示:
1 <= n <= 2 * 10^4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-vowels-permutation
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
一个简单的动态规划
可以用矩阵快速幂写
class Solution
int MOD = (int)1e9 + 7;
public int countVowelPermutation(int n)
//感觉像那种状态机转移的方法
//是不是动态规划
//0 1 2 3 4 分别代表a e i o u结尾
//
int[][] f = new int[n][5];
for(int i = 0; i < 5; i++)
f[0][i] = 1;
for(int i = 1; i < n; i++)
f[i][0] = ((f[i - 1][1] + f[i - 1][2]) % MOD + f[i - 1][4]) % MOD;
f[i][1] = (f[i - 1][0] + f[i - 1][2]) % MOD;
f[i][2] = (f[i - 1][1] + f[i - 1][3]) % MOD;
f[i][3] = f[i - 1][2];
f[i][4] = (f[i - 1][2] + f[i - 1][3]) % MOD;
int ans = 0;
for(int i = 0; i < 5; i++)
ans = (ans + f[n - 1][i]) % MOD;
return ans;
以上是关于LeetCode 1716. 计算力扣银行的钱 / 382. 链表随机节点(蓄水池抽样) / 1220. 统计元音字母序列的数目(动规,矩阵快速幂)的主要内容,如果未能解决你的问题,请参考以下文章