leetcode day6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
剑指offer
13 机器人的运动范围
题目:地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
想法1:BFS
class Solution {
int get(int num){
int res = 0;
int ge = num % 10;
int shi = (num - ge) / 10;
res = ge + shi;
return res;
}
public:
int movingCount(int m, int n, int k) {
int count = 1;
queue<pair<int, int> > Q;
Q.push(make_pair(0, 0));
int dx[2] = { 0, 1 };
int dy[2] = { 1, 0 };
vector<vector<int>> isVisited(m, vector<int>(n, 0));
isVisited[0][0] = 1;
while (!Q.empty()) {
auto [x,y] = Q.front();
Q.pop();
for (int i = 0;i < 2;i++) {
int newx = x + dx[i];
int newy = y + dy[i];
int he = get(newx) + get(newy);
if (newx >= m || newy >= n) {
continue;
}
if ((he <= k) && (isVisited[newx][newy]==0) && (newx<m) && (newy<n)) {
Q.push(make_pair(newx, newy));
count++;
isVisited[newx][newy] = 1;
}
}
}
return count;
}
};
想法2:DFS递推
class Solution {
public:
int movingCount(int m, int n, int k) {
vector<vector<bool>> visited(m, vector<bool>(n, 0));
return dfs(0, 0, 0, 0, visited, m, n, k);
}
private:
int dfs(int i, int j, int si, int sj, vector<vector<bool>> &visited, int m, int n, int k) {
if(i >= m || j >= n || k < si + sj || visited[i][j]) return 0;
visited[i][j] = true;
return 1 + dfs(i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj, visited, m, n, k) +
dfs(i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8, visited, m, n, k);
}
};
作者:jyd
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/mian-shi-ti-13-ji-qi-ren-de-yun-dong-fan-wei-dfs-b/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
17 打印从1到最大的n位数
题目:输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
我的思路:…暴力?过…过了?
class Solution(object):
def printNumbers(self, n):
"""
:type n: int
:rtype: List[int]
"""
return range(1,10**n)
其他思路:考虑大数的打印(越界),用string。观察可知,生成的列表实际上是 n 位 0 - 9 的 全排列 ,因此可避开进位操作,通过递归生成数字的 String 列表。(树,dfs
class Solution:
def printNumbers(self, n: int) -> [int]:
def dfs(x):
if x == n:
s = ''.join(num[self.start:])
if s != '0': res.append(s)
if n - self.start == self.nine: self.start -= 1
return
for i in range(10):
if i == 9: self.nine += 1
num[x] = str(i)
dfs(x + 1)
self.nine -= 1
num, res = ['0'] * n, []
self.nine = 0
self.start = n - 1
dfs(0)
return ','.join(res)
作者:jyd
链接:https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/solution/mian-shi-ti-17-da-yin-cong-1-dao-zui-da-de-n-wei-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
14 剪绳子
题目:给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
思路一:动态规划
int cuttingRope(int n) {
if (n==0)return 0;
else if(n<3)return 1;
else if(n==3)return 2;
vector<int> dp(n + 1, 0);
dp[0] = 0;
dp[1] = 1;
dp[2] = 1;
dp[3] = 2;
// 动态规划
for (int i = 2;i <= n;i++) {
for (int j = 2;j < i;j++) {
dp[i] = max(dp[i], max(dp[i - j] * j, j * (i - j)));
}
}
return dp[n];
}
思路二:贪心——尽可能把绳子分成长度为3的小段,这样乘积最大
步骤如下:
如果 n == 2,返回1,如果 n == 3,返回2,
如果 n == 4,返回4
如果 n > 4,分成尽可能多的长度为3的小段,每次循环长度n减去3,乘积res乘以3;最后返回时乘以小于等于4的最后一小段
我也许该去写一下大数的运算(捂脸
int cuttingRope(int n) {
if(n<4){
return n-1;
}
else if(n==4){
return 4;
}
int res=1;
int res2=1;
while(n>4){
res2=(res+res)%1000000007;
res=(res2+res)%1000000007;
n-=3;
}
if(n==2){
res=(res+res)%1000000007;
}
else if(n==3){
res2=(res+res)%1000000007;
res=(res2+res)%1000000007;
}
else if(n==4){
res2=(res+res)%1000000007;
res2=(res2+res)%1000000007;
res=(res2+res)%1000000007;
}
return res;
}