给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例 2:
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
public ListNode rotateRight(ListNode head, int k) {
if(head == null) return null;
// 计算链表的节点数
int n = 0;
for(ListNode p = head; p != null; p = p.next) n++;
// 取余
k %= n;
// 快指针前进k步
ListNode slow = head, fast = head;
while(k -- > 0) fast = fast.next;
while(fast.next!= null){
fast = fast.next;
slow = slow.next;
}
// 节点交换 画图查看
fast.next = head;
head = slow.next;
slow.next = null;
return head;
}
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
例如,上图是一个7 x 3 的网格。有多少可能的路径?
示例 1:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例 2:
输入: m = 7, n = 3
输出: 28
提示:
public int uniquePaths(int m, int n) {
//f[m,n]表示走到m,n的路径 res = f[m-1][n-1]
int[][] f = new int[m][n];
for(int i = 0; i < m; i ++){
for(int j = 0; j < n; j++){
// 第一行 和 第一列 只能从同一个方向过来
if(i == 0 || j == 0) f[i][j] = 1;
// 其他的位置 都有两个方向的来源
else f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
return f[m - 1][n - 1];
}
public int uniquePaths(int m, int n) {
int[] f = new int[n];
Arrays.fill(f, 1);
for(int i = 1; i < m; i ++){
for(int j = 1; j < n; j ++){
f[j] += f[j - 1];
}
}
return f[n - 1];
}
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
示例 1:
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
示例 2:
输入:obstacleGrid = [[0,1],[0,0]]
输出:1
提示:
第一行第一列的情况: 一旦遇到障碍物, 后续的位置便都是0。
其他情况:从上或左方向来,障碍物的位置f = 0。
class Solution {
public int uniquePathsWithObstacles(int[][] g) {
int n = g.length, m = g[0].length;
//f[m,n]表示走到m,n的路径 res = f[m-1][n-1]
int[][] f = new int[n][m];
// 初始化第一列
for(int i = 0; i < n && g[i][0] == 0; i ++) f[i][0] = 1;
// 初始化第一行
for(int i = 0; i < m && g[0][i] == 0; i ++) f[0][i] = 1;
// 其他位置
for(int i = 1; i < n; i ++){
for(int j = 1; j < m; j ++){
if(g[i][j] == 1) continue;
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
return f[n - 1][m - 1];
}
}
class Solution {
public int uniquePathsWithObstacles(int[][] g) {
int n = g.length, m = g[0].length;
int[] f = new int[m];
f[0] = g[0][0] == 0 ? 1 : 0;
for(int i = 0; i < n; i ++){
for(int j = 0; j < m; j ++){
if(g[i][j] == 1) {
f[j] = 0;
continue;
}
if(j - 1 >= 0 && g[i][j - 1] == 0){
f[j] += f[j - 1];
}
}
}
return f[m - 1];
}
}
难度中等793收藏分享切换为英文接收动态反馈
给定一个包含非负整数的 *m* x *n* 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例 1:
输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。
示例 2:
输入:grid = [[1,2,3],[4,5,6]]
输出:12
提示:
class Solution {
// 在grid 上原地操作
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i == 0 && j == 0) {
continue;
// 第一行 只能从左边来
} else if (i == 0) {
grid[i][j] += grid[i][j - 1];
// 第一列 只能从上面来
} else if (j == 0) {
grid[i][j] += grid[i - 1][j];
// 取相对小的一个
} else {
grid[i][j] += Math.min(grid[i][j - 1],grid[i - 1][j]);
}
}
}
return grid[m - 1][n - 1];
}
}
有效数字(按顺序)可以分成以下几个部分:
小数(按顺序)可以分成以下几个部分:
整数(按顺序)可以分成以下几个部分:
部分有效数字列举如下:
部分有效数字列举如下:
给你一个字符串 s ,如果 s 是一个 有效数字 ,请返回 true 。
示例 1:
输入:s = "0"
输出:true
示例 2:
输入:s = "e"
输出:false
示例 3:
输入:s = "."
输出:false
示例 4:
输入:s = ".1"
输出:true
提示:
class Solution {
// https://leetcode.com/problems/valid-number/discuss/1066333/Java-Easy-Solution-(with-comments)
public boolean isNumber(String s) {
boolean sign = false;
boolean digit = false;
boolean e = false;
boolean dots = false;
for(int i = 0; i < s.length(); i ++){
// ±号的情况,满足条件: 只能出现一次符号且该位置是第一位或者前面是e
if(s.charAt(i) == '+' || s.charAt(i) == '-') {
if((i == 0 || s.charAt(i - 1) == 'e') && !sign){
sign = true;
continue;
}else return false;
}
// 数字的限制较少, 直接标记一下并跳过
if(s.charAt(i) >= '0' && s.charAt(i) <= '9'){
digit = true;
continue;
}
// 不能遇到点 或者 e
if(s.charAt(i) == '.'){
if(e || dots) return false;
dots = true;
continue;
}
// 如果是e,前面要出现过数字,且没有出现e
if((s.charAt(i) == 'e' || s.charAt(i) == 'E') && digit && !e){
digit = false;
sign = false;
e = true;
continue;
}else return false;
}
if(digit) return true;
else return false;
}
}
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 1:
输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:
输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
public int[] plusOne(int[] digits) {
for(int i = digits.length - 1; i >= 0; i --){
if(digits[i] != 9){
digits[i] ++;
return digits;
}
digits[i] = 0;
}
// 每个都是0 1000
int[] res = new int[digits.length + 1];
res[0] = 1;
return res;
}
给你两个二进制字符串,返回它们的和(用二进制表示)。
输入为 非空 字符串且只包含数字 1 和 0。
示例 1:
输入: a = "11", b = "1"
输出: "100"
示例 2:
输入: a = "1010", b = "1011"
输出: "10101"
提示:
class Solution {
public String addBinary(String a, String b) {
int c = 0; // 进位
int i = a.length() - 1, j = b.length() - 1;
StringBuilder ans = new StringBuilder();
int aa = 0, bb = 0;
while(i >= 0 || j >= 0){
aa = i < 0 ? 0 : a.charAt(i --) - '0';
bb = j < 0 ? 0 : b.charAt(j --) - '0';
c += aa + bb;
ans.append(c % 2);
c >>= 1;
}
if(c > 0) ans.append(c);
return ans.reverse().toString();
}
}
给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth个字符,且左右两端对齐的文本。
你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。
要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
文本的最后一行应为左对齐,且单词之间不插入额外的空格。
说明:
示例:
输入:
words = ["What","must","be","acknowledgment","shall","be"]
maxWidth = 16
输出:
[
"What must be",
"acknowledgment ",
"shall be "
]
解释: 注意最后一行的格式应为 "shall be " 而不是 "shall be",
因为最后一行应为左对齐,而不是左右两端对齐。
第二行同样为左对齐,这是因为这行只包含一个单词。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/text-justification
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
https://www.youtube.com/watch?v=GqXlEbFVTXY
class Solution {
public List fullJustify(String[] words, int maxWidth) {
List res = new ArrayList<>();
int i = 0, n = words.length;
// 双指针,划定每一行的单词范围
while(i < n){
int j = i + 1;
int lineLength = words[i].length();
while(j < n &&
(lineLength + words[j].length() + (j - i - 1) < maxWidth)){
lineLength += words[j].length();
++ j;
}
int diff = maxWidth - lineLength;
// 单词数量
int numberOfWords = j - i;
if(numberOfWords == 1 || j >= n) res.add(leftJustify(words, diff, i, j));
else res.add(middleJustify(words, diff, i, j));
i = j;
}
return res;
}
// 一行的单词数量只有一个 或者最后一行 左对齐
String leftJustify(String[] words, int diff, int i, int j){
int spaceOnRight = diff - (j - i - 1);// 右边需要补充的空格数
StringBuilder res = new StringBuilder(words[i]);
for(int k = i + 1; k < j; k ++){
res.append(" " + words[k]);
}
res.append(" ".repeat(spaceOnRight));
return res.toString();
}
// 左右两端对齐
String middleJustify(String[] words, int diff, int i, int j){
int spacesNeeded = j - i - 1;
int spaces = diff / spacesNeeded;
int extraSpaces = diff % spacesNeeded;
StringBuilder res = new StringBuilder(words[i]);
for(int k = i + 1; k < j; k ++){
int spacesToApply = spaces + (extraSpaces-- > 0 ? 1 : 0);
res.append(" ".repeat(spacesToApply) + words[k]);
}
return res.toString();
}
}
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
class Solution {
public int mySqrt(int x) {
if(x == 1) return 1;
int l = 0, r = x / 2;
while( l < r ){
int mid = l + r + 1 >> 1;
if (mid <= x / mid) l = mid;
else r = mid - 1;
}
return r;
}
}
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
public int climbStairs(int n) {
if (n <= 2) {
return n;
}
int[] f = new int[n + 1];
f[1] = 1;
f[2] = 2;
for (int i = 3; i <= n; i++) {
f[i] = f[i - 1] + f[i - 2];
}
return f[n];
}
class Solution {
public int climbStairs(int n) {
int a = 0, b = 0, c = 1;
for (int i = 1; i <= n; ++i) {
a = b;
b = c;
c = a + b;
}
return c;
}
}
时间复杂度 O(N)
原文链接:https://www.cnblogs.com/summerday152/p/14449093.html
如果觉得本文对你有帮助,可以关注一下我公众号,回复关键字【面试】即可得到一份Java核心知识点整理与一份面试大礼包!另有更多技术干货文章以及相关资料共享,大家一起学习进步!