实现 MyStack 类:
void push(int x)
将元素 x 压入栈顶。
int pop()
移除并返回栈顶元素。
int top()
返回栈顶元素。
boolean empty()
如果栈是空的,返回 true ;否则,返回 false 。
注意:
- 你只能使用队列的基本操作 —— 也就是
push to back
、peek/pop from front
、size
和is empty
这些操作。 - 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
示例:
输入:
[“MyStack”, “push”, “push”, “top”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]
解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
提示:
- 1 <= x <= 9
- 最多调用100 次 push、pop、top 和 empty
- 每次调用 pop 和 top 都保证栈不为空
进阶:你能否实现每种操作的均摊时间复杂度为 O(1) 的栈?换句话说,执行 n 个操作的总时间复杂度 O(n) ,尽管其中某个操作可能需要比其他操作更长的时间。你可以使用两个以上的队列。
#include <bits/stdc++.h>
using namespace std;
class MyStack
{
public:
MyStack()
{
}
void push(int x)
{
std::queue<int> temp_queue;
temp_queue.push(x);
while (!_data.empty())
{
temp_queue.push(_data.front());
_data.pop();
}
while (!temp_queue.empty())
{
_data.push(temp_queue.front());
temp_queue.pop();
}
}
int pop()
{
int x = _data.front();
_data.pop();
return x;
}
int top()
{
return _data.front();
}
bool empty()
{
return _data.empty();
}
private:
std::queue<int> _data;
};
生成100个2位随机正整数,按每行十个输出,并求出个位数字分别为0,1,2,3,4,5,6,7,8,9的正整数的个数
import random
def fun():
random_list = [random.randint(10, 99) for n in range(100)]
statistics = {n: 0 for n in range(10)}
for index, x in enumerate(random_list):
print(x, end=' ')
statistics[int(x % 10)] = statistics[int(x % 10)] + 1
if ((index + 1) % 10 == 0):
print()
print(statistics)
if __name__ == '__main__':
fun()
问题描述:
给定一个整数数组 nums,请找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
示例 1:
输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:
输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
class Solution:
def maxProduct(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
length = len(nums)
dp = [[0] * 2 for _ in range(length)]
dp[0][0] = nums[0]
dp[0][1] = nums[0]
for i in range(1, length):
if nums[i] > 0:
dp[i][0] = min(nums[i], dp[i - 1][0] * nums[i])
dp[i][1] = max(nums[i], dp[i - 1][1] * nums[i])
else:
dp[i][0] = min(nums[i], dp[i - 1][1] * nums[i])
dp[i][1] = max(nums[i], dp[i - 1][0] * nums[i])
res = dp[0][1]
for i in range(1, length):
res = max(res, dp[i][1])
return res
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例 1:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
输出:true
示例 2:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “SEE”
输出:true
示例 3:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCB”
输出:false
提示:
m == board.length
n = board[i].length
1 <= m, n <= 6
1 <= word.length <= 15
board 和 word 仅由大小写英文字母组成
进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?
class Solution(object):
def exist(self, board, word):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
check_board = [[True] * len(board[0]) for _ in range(len(board))]
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] == word[0] and check_board:
check_board[i][j] = False
res = self.check_exist(check_board, board, word, 1, len(word), i, j)
if res:
return True
check_board[i][j] = True
return False
def check_exist(self, check_board, board, word, index, ls, row, col):
if index == ls:
return True
for temp in [(0, 1),(0, -1),(1, 0),(-1, 0)]:
curr_row = row + temp[0]
curr_col = col + temp[1]
if curr_row >= 0 and curr_row < len(board) and curr_col >= 0 and curr_col < len(board[0]):
if check_board[curr_row][curr_col] and board[curr_row][curr_col] == word[index]:
check_board[curr_row][curr_col] = False
res = self.check_exist(check_board, board, word, index + 1, len(word), curr_row, curr_col)
if res:
return res
check_board[curr_row][curr_col] = True
return False
if __name__ == "__main__":
s = Solution()
print (s.exist(board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"))
矩阵置零
给定一个 m x n
的矩阵,如果一个元素为 0
,则将其所在行和列的所有元素都设为 0
。请使用 原地算法 算法。
进阶:
一个直观的解决方案是使用 O(mn)
的额外空间,但这并不是一个好的解决方案。
一个简单的改进方案是使用 O(m + n)
的额外空间,但这仍然不是最好的解决方案。
你能想出一个仅使用常量空间的解决方案吗?
示例 1:
输入:
matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:
[[1,0,1],[0,0,0],[1,0,1]]
示例 2:
输入:
matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:
[[0,0,0,0],[0,4,5,0],[0,3,1,0]]
提示:
m == matrix.length
n == matrix[0].length
1 <= m, n <= 200
-2^31 <= matrix[i][j] <= 2^31 - 1
解题思路:
这道题要求原地修改矩阵,即不使用额外的空间。我们可以使用第一行和第一列来记录每一行和每一列是否需要被置零。具体步骤如下:
-
遍历矩阵,如果某个元素
matrix[i][j]
为零,将matrix[i][0]
和matrix[0][j]
设置为零,用于标记该行和该列需要被置零。 -
再次遍历矩阵,如果
matrix[i][0]
或matrix[0][j]
为零,将matrix[i][j]
置零。 -
最后,根据第一行和第一列的标记,将第一行和第一列的元素置零。
这样,我们在不使用额外空间的情况下,成功地将矩阵中的零元素进行了标记和置零。以下是具体的代码实现:
class Solution {
public void setZeroes(int[][] matrix) {
int[] xNum = new int[matrix[0].length];
int[] yNum = new int[matrix.length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] == 0) {
xNum[j] = 1;
yNum[i] = 1;
}
}
}
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (xNum[j] == 1 || yNum[i] == 1) {
matrix[i][j] = 0;
}
}
}
}
}
这个算法的时间复杂度为 O(mn),空间复杂度为 O(1)。
单词搜索 II
给定一个 m x n
二维字符网格 board
和一个单词(字符串)列表 words
,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中相邻单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例 1:
输入:
board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]]
words = ["oath","pea","eat","rain"]
输出:
["eat","oath"]
示例 2:
输入:
board = [["a","b"],["c","d"]]
words = ["abcb"]
输出:
[]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 12
board[i][j]
是一个小写英文字母1 <= words.length <= 3 * 10^4
1 <= words[i].length <= 10
words[i]
由小写英文字母组成words
中的所有字符串互不相同
解题思路:
这道题可以使用字典树(Trie)结构来进行搜索。首先,将 words
中的单词构建成一个 Trie 树。然后,遍历二维网格 board
中的每个单元格,从每个单元格出发,通过 DFS 深度优先搜索来查找可能的单词。
具体步骤如下:
-
构建 Trie 树:遍历
words
中的每个单词,将其插入 Trie 树中。同时,可以为每个 Trie 节点存储一个额外的标记,表示该节点对应的单词是否在words
中。 -
遍历二维网格
board
:遍历每个单元格,以每个单元格为起点,进行 DFS 搜索。在搜索过程中,需要判断当前字符是否是 Trie 树中某个单词的前缀,如果不是,则可以提前终止搜索。 -
DFS 搜索:从当前单元格出发,首先检查当前字符是否在 Trie 树中,如果不在,则返回。否则,将当前字符标记为已访问,然后递归地搜索其相邻的未访问过的单元格。在搜索过程中,需要维护一个字符串,记录当前路径上的字符。
-
收集结果:如果当前路径上的字符串在 Trie 树中,表示找到一个匹配的单词,将其添加到结果集中。需要注意的是,在结果集中添加后,需要将 Trie 树中的标记清除,以避免重复添加。
以下是具体的代码实现:
class Solution {
static int[][] d = new int[][] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
static Map<String, Boolean> notExistWords = new HashMap<>();
public List<String> findWords(char[][] board, String[] words) {
List<String> ans = new ArrayList<>();
Arrays.sort(words);
notExistWords.clear();
for (int i = 0; i < words.length; i++) {
String word = words[i];
if (i > 0 && word.equals(words[i - 1]))
continue;
boolean notExistFlag = false;
for (int j = 1; j < word.length(); j++) {
if (notExistWords.containsKey(word.substring(0, j + 1))) {
notExistFlag = true;
break;
}
}
if (notExistFlag)
continue;
if (exist(board, word)) {
ans.add(word);
} else {
notExistWords.put(word, false);
}
}
return ans;
}
public boolean exist(char[][] board, String word) {
int m = board.length;
if (m == 0)
return false;
int n = board[0].length;
if (n == 0)
return false;
if (word.equals(""))
return true;
boolean[][] f = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (word.charAt(0) == board[i][j]) {
f[i][j] = true;
boolean flag = dfs(i, j, 1, board, word, m, n, f);
if (flag)
return true;
f[i][j] = false;
}
}
}
return false;
}
private boolean dfs(int i, int j, int k, char[][] board, String word, int m, int n, boolean[][] f) {
if (k == word.length()) {
return true;
}
for (int l = 0; l < 4; l++) {
if (i + d[l][0] < m && j + d[l][1] < n && i + d[l][0] >= 0 && j + d[l][1] >= 0
&& board[i + d[l][0]][j + d[l][1]] == word.charAt(k) && !f[i + d[l][0]][j + d[l][1]]) {
f[i + d[l][0]][j + d[l][1]] = true;
boolean flag = dfs(i + d[l][0], j + d[l][1], k + 1, board, word, m, n, f);
if (flag)
return true;
f[i + d[l][0]][j + d[l][1]] = false;
}
}
return false;
}
}
Excel表列序号
给定一个字符串 columnTitle
,表示 Excel 表格中的列名称。返回该列名称对应的列序号。
例如,
A -> 1
B -> 2
C -> 3
…
Z -> 26
AA -> 27
AB -> 28
…
示例 1:
输入: columnTitle = "A"
输出: 1
示例 2:
输入: columnTitle = "AB"
输出: 28
示例 3:
输入: columnTitle = "ZY"
输出: 701
示例 4:
输入: columnTitle = "FXSHRXW"
输出: 2147483647
提示:
- 1 <= columnTitle.length <= 7
- columnTitle 仅由大写英文组成
- columnTitle 在范围 [“A”, “FXSHRXW”] 内
class Solution {
public int titleToNumber(String s) {
char[] charArray = s.toCharArray();
int res = 0;
for (int i = 0; i < charArray.length; i++) {
res = res * 26 + (charArray[i] - 'A' + 1);
}
return res;
}
}
删除链表中的元素
给定一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回新的头节点。
示例
示例 1
输入:head = [1,2,6,3,4,5,6]
, val = 6
输出:[1,2,3,4,5]
示例 2
输入:head = []
, val = 1
输出:[]
示例 3
输入:head = [7,7,7,7]
, val = 7
输出:[]
提示
- 列表中的节点数目在范围 [0, 10^4] 内
- 1 <= Node.val <= 50
- 0 <= val <= 50
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode top = new ListNode(0);
top.next = head;
ListNode pre = top;
ListNode temp = head;
while (temp != null) {
if (temp.val == val)
pre.next = temp.next;
else
pre = temp;
temp = temp.next;
}
return top.next;
}
}
城市天际线
城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回由这些建筑物形成的天际线。
每个建筑物的几何信息由数组 buildings 表示,其中三元组 buildings[i] = [lefti, righti, heighti] 表示:
- lefti 是第 i 座建筑物左边缘的 x 坐标。
- righti 是第 i 座建筑物右边缘的 x 坐标。
- heighti 是第 i 座建筑物的高度。
天际线应该表示为由 “关键点” 组成的列表,格式 [[x1,y1],[x2,y2],…] ,并按 x 坐标 进行排序。关键点是水平线段的左端点。列表中最后一个点是最右侧建筑物的终点,y 坐标始终为 0 ,仅用于标记天际线的终点。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。
注意:输出天际线中不得有连续的相同高度的水平线。例如 […[2 3], [4 5], [7 5], [11 5], [12 7]…] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[…[2 3], [4 5], [12 7], …]
示例 1:
输入
buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
输出
[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
解释
- 图 A 显示输入的所有建筑物的位置和高度,
- 图 B 显示由这些建筑物形成的天际线。图 B 中的红点表示输出列表中的关键点。
示例 2:
输入
buildings = [[0,2,3],[2,5,3]]
输出
[[0,3],[5,0]]
提示
- 1 <= buildings.length <= 10^4
- 0 <= lefti < righti <= 2^31 - 1
- 1 <= heighti <= 2^31 - 1
- buildings 按 lefti 非递减排序
class Solution {
public List<List<Integer>> getSkyline(int[][] buildings) {
int n = buildings.length, m = n << 1;
List<List<Integer>> ans = new ArrayList<List<Integer>>();
int[] boundaries = new int[m];
for (int i = 0; i < n; i++) {
boundaries[i << 1] = buildings[i][0];
boundaries[(i << 1) + 1] = buildings[i][1];
}
Arrays.sort(boundaries);
PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a, b) -> b[1] - a[1]);
int building = 0;
for (int i = 0; i < m; i++) {
if (i > 0 && boundaries[i - 1] == boundaries[i])
continue;
while (building < n && buildings[building][0] <= boundaries[i])
pq.offer(new int[] { buildings[building][1], buildings[building++][2] });
while (!pq.isEmpty() && pq.peek()[0] <= boundaries[i])
pq.poll();
int height = (pq.isEmpty()) ? 0 : pq.peek()[1];
if (ans.size() == 0 || height != ans.get(ans.size() - 1).get(1))
ans.add(Arrays.asList(boundaries[i], height));
}
return ans;
}
}
生成螺旋矩阵的示例:
示例 1:
输入: n = 3
输出:
[
[ 1, 2, 3],
[ 8, 9, 4],
[ 7, 6, 5]
]
示例 2:
输入: n = 1
输出: [[1]]
提示:
1 <= n <= 20
package LeetCode;
public class GenerateMatrix {
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
if (n == 0) {
return res;
}
int left = 0;
int right = n - 1;
int up = 0;
int down = n - 1;
int i = 1;
while (i <= n * n) {
for (int col = left; col <= right; col++) {
res[up][col] = i;
i++;
}
up++;
if (i <= n * n) {
for (int j = up; j <= down; j++) {
res[j][right] = i;
i++;
}
right--;
}
if (i <= n * n) {
for (int j = right; j >= left; j--) {
res[down][j] = i;
i++;
}
down--;
}
if (i <= n * n) {
for (int j = down; j >= up; j--) {
res[j][left] = i;
i++;
}
left++;
}
}
return res;
}
public static void main(String[] args) {
GenerateMatrix a = new GenerateMatrix();
a.generateMatrix(3);
}
}
实现 pow(x, n) 函数:
给定 x 和 n,计算 x 的 n 次幂。
示例 1:
输入:
x = 2.00000, n = 10
输出:
1024.00000
示例 2:
输入:
x = 2.10000, n = 3
输出:
9.26100
示例 3:
输入:
x = 2.00000, n = -2
输出:
0.25000
解释:
2^-2 = 1/(2^2) = 1/4 = 0.25
提示:
-100.0 < x < 100.0
-231 <= n <= 231-1
-104 <= x^n <= 104
public class Solution {
public double myPow(double x, int n) {
if (n < 0) {
return 1 / pow(x, -n);
} else {
return pow(x, n);
}
}
private double pow(double x, int n) {
if (n == 0) {
return 1.0;
}
if (n == 1) {
return x;
}
double val = pow(x, n / 2);
if (n % 2 == 0) {
return val * val;
} else {
return val * val * x;
}
}
}
最小路径和问题:
给定一个非负整数的 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
提示:
- m == grid.length
- n == grid[i].length
- 1 <= m, n <= 200
- 0 <= grid[i][j] <= 100
class Solution {
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int sum = 0;
if (m < 1 || n < 1)
return 0;
if (m == 1) {
for (int i = 0; i < n; i++) {
sum = sum + grid[0][i];
}
return sum;
}
if (n == 1) {
for (int i = 0; i < m; i++) {
sum = sum + grid[i][0];
}
return sum;
}
int[][] dp = new int[m][n];
dp[0][0] = grid[0][0];
for (int k = 1; k < m; k++) {
dp[k][0] = grid[k][0] + dp[k - 1][0];
}
for (int l = 1; l < n; l++) {
dp[0][l] = grid[0][l] + dp[0][l - 1];
}
for (int k = 1; k < m; k++) {
for (int l = 1; l < n; l++) {
dp[k][l] = grid[k][l] + Math.min(dp[k - 1][l], dp[k][l - 1]);
}
}
return dp[m - 1][n - 1];
}
}
设计一个支持平均时间复杂度 O(1) 的数据结构:
设计一个数据结构,支持以下操作:
- insert(val):向集合中插入元素 val。
- remove(val):当 val 存在时,从集合中移除一个 val。
- getRandom:从现有集合中随机获取一个元素,每个元素被返回的概率应该与其在集合中的数量呈线性相关。
示例:
// 初始化一个空的集合。
RandomizedCollection collection = new RandomizedCollection();
// 向集合中插入 1 。返回 true 表示集合不包含 1 。
collection.insert(1);
// 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
collection.insert(1);
// 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
collection.insert(2);
// getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
collection.getRandom();
// 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
collection.remove(1);
// getRandom 应有相同概率返回 1 和 2 。
collection.getRandom();
这个数据结构需要在插入、删除和获取随机元素这三个操作上都满足平均时间复杂度 O(1) 的要求。
class RandomizedCollection {
private Map<Integer, Set<Integer>> map;
private List<Integer> list;
private Random random;
private int size = 0;
public RandomizedCollection() {
map = new HashMap<>();
list = new ArrayList<>();
random = new Random();
}
public boolean insert(int val) {
if (map.containsKey(val)) {
Set<Integer> indexes = map.get(val);
list.add(size, val);
indexes.add(size);
size++;
return false;
} else {
Set<Integer> indexes = new HashSet<>();
map.put(val, indexes);
list.add(size, val);
indexes.add(size);
size++;
return true;
}
}
public boolean remove(int val) {
if (!map.containsKey(val)) {
return false;
}
Set<Integer> indexes = map.get(val);
if (list.get(size - 1) == val) {
indexes.remove(size - 1);
size--;
} else {
Iterator<Integer> it = indexes.iterator();
int index = it.next();
it.remove();
int last = list.get(size - 1);
list.set(index, last);
Set<Integer> set = map.get(last);
set.remove(size - 1);
set.add(index);
size--;
}
if (indexes.size() == 0) {
map.remove(val);
}
return true;
}
public int getRandom() {
return list.get(random.nextInt(size));
}
}
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection obj = new RandomizedCollection();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/
矩形区域不超过 K 的最大数值和
题目:
给定一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。
示例 1:
输入:matrix = [[1,0,1],[0,-2,3]], k = 2
输出:2
解释:蓝色边框圈出来的矩形区域 [[0, 1], [-2, 3]] 的数值和是 2,且 2 是不超过 k 的最大数字(k = 2)。
示例 2:
输入:matrix = [[2,2,-1]], k = 3
输出:3
提示:
- m == matrix.length
- n == matrix[i].length
- 1 <= m, n <= 100
- -100 <= matrix[i][j] <= 100
- -10^5 <= k <= 10^5
进阶: 如果行数远大于列数,该如何设计解决方案?
import bisect
class Solution:
def maxSumSubmatrix(self, matrix: List[List[int]], k: int) -> int:
m = len(matrix)
Row, Col = len(matrix), len(matrix[0])
res = float("-inf")
for ru in range(Row):
col_sum = [0 for _ in range(Col)]
for rd in range(ru, Row):
for c in range(Col):
if matrix[rd][c] == k:
return k
col_sum[c] += matrix[rd][c]
presum = [0]
cur_sum = 0
for colsum in col_sum:
cur_sum += colsum
idx = bisect.bisect_left(presum, cur_sum - k)
if idx < len(presum):
res = max(res, cur_sum - presum[idx])
if res == k:
return k
bisect.insort(presum, cur_sum)
return res
冒泡排序
用冒泡排序编写一个函数,允许接受多个数字的输入,不使用sort方法,给数字从小到大排序,最终输出从小到大的列表。
#!/usr/bin/python3
def bubbleSort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1] :
arr[j], arr[j+1] = arr[j+1], arr[j]
x=input("请输入数字,空格分隔:")
xlist=x.split(" ")
arr = [int(xlist[i]) for i in range(len(xlist))]
bubbleSort(arr)
print ("排序后的数组:")
for i in range(len(arr)):
print ("%d" %arr[i])
判断快乐数
编写一个算法来判断一个数 n 是不是快乐数。
快乐数的定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。
- 如果可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。
示例
示例 1
输入:19
输出:true
解释:
- 1 2 + 9 2 = 82 1^2 + 9^2 = 82 12+92=82
- 8 2 + 2 2 = 68 8^2 + 2^2 = 68 82+22=68
- 6 2 + 8 2 = 100 6^2 + 8^2 = 100 62+82=100
- 1 2 + 0 2 + 0 2 = 1 1^2 + 0^2 + 0^2 = 1 12+02+02=1
示例 2
输入:n = 2
输出:false
提示
1 ≤ n ≤ 2 31 − 1 1 \le n \le 2^{31} - 1 1≤n≤231−1
class Solution(object):
def isHappy(self, n):
"""
:type n: int
:rtype: bool
"""
d = {}
while True:
l = list(map(int, list(str(n))))
m = 0
for i in l:
m += i ** 2
if m in d:
print(d)
return False
if m == 1:
print(d)
return True
d[m] = m
n = m
删除有序数组中的重复项
给你一个有序数组 nums
,请你 原地删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地修改输入数组 并在使用 O(1) 额外空间的条件下完成。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
# nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums
已按升序排列
class Solution(object):
def removeDuplicates(self, nums):
if len(nums) == 0:
return 0
left = 0
for i in range(1, len(nums)):
if nums[left] == nums[i]:
continue
else:
left += 1
nums[left] = nums[i]
return left + 1
# %%
s = Solution()
print(s.removeDuplicates(nums = [1,1,2]))
计算出因子里面4和7的个数
输入一个正数n,计算出因子里面分别有几个4和7,输出因子中4和7的个位数
以下程序实现了这一功能,请你填补空白处内容:
n = int(input("输入数字:"))
factor = [n]
num = 1
while num <= n/2+1:
if n % num == 0:
factor.append(num)
num = num + 1
print(factor)
m = [str(i) for i in factor]
count4 = 0
count7 = 0
for i in m:
if '4' in i:
count4 += 1
print('以4结尾的因子的个位数:', int(i)%10)
if '7' in i:
count7 += 1
print('以7结尾的因子的个位数:', int(i)%10)
print('因子里面分别有{0}个4和{1}个7'.format(count4,count7))
#路径总和II
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1],
targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]
示例 2
输入:root = [1,2,3], targetSum = 5
输出:[]
示例 3:
输入:root = [1,2], targetSum = 0
输出:[]
提示:
树中节点总数在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
class Solution:
def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
pathvalue = 0
path = []
result = []
def preorder(node, pathvalue, sum, path, result):
if node == None:
return
pathvalue += node.val
path.append(node.val)
if pathvalue == sum and node.left == None and node.right == None:
result.append(list(path)) # 注意加list
preorder(node.left, pathvalue, sum, path, result)
preorder(node.right, pathvalue, sum, path, result)
pathvalue -= node.val
path.pop()
preorder(root, pathvalue, sum, path, result)
return result
最大子数组和
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例
示例 1
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1]
的和最大,为 6
。
示例 2
输入:nums = [1]
输出:1
示例 3
输入:nums = [0]
输出:0
示例 4
输入:nums = [-1]
输出:-1
示例 5
输入:nums = [-100000]
输出:-100000
提示
1 <= nums.length <= 3 * 104
-105 <= nums[i] <= 105
进阶
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
#include <bits/stdc++.h>
using namespace std;
class Solution
{
public:
int maxSubArray(vector<int> &nums)
{
int sum = 0, max_sum = INT_MIN;
for (int i = 0; i < nums.size(); i++)
{
if (sum < 0)
{
sum = nums[i];
}
else
{
sum += nums[i];
}
max_sum = max(sum, max_sum);
}
return max_sum;
}
};
外观数列
给定一个正整数 n
,输出外观数列的第 n
项。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
你可以将其视作是由递归公式定义的数字字符串序列:
- countAndSay(1) = “1”
- countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。
前五项如下:
- 1
- 11
- 21
- 1211
- 111221
第一项是数字 1,描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 “11”。描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 “21”。描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 “1211”。描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 “111221”。
要描述一个数字字符串,首先要将字符串分割为最小数量的组,每个组都由连续的最多相同字符组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。
示例
示例 1
输入:n = 1
输出:“1”
解释:这是一个基本样例。
示例 2
输入:n = 4
输出:“1211”
解释:
- countAndSay(1) = “1”
- countAndSay(2) = 读 “1” = 一 个 1 = “11”
- countAndSay(3) = 读 “11” = 二 个 1 = “21”
- countAndSay(4) = 读 “21” = 一 个 2 + 一 个 1 = “12” + “11” = “1211”
提示
1 <= n <= 30
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void parse(char *input, char *output)
{
char *p = input;
char *q = output;
while (*p != '\0')
{
int count = 1;
while (p[0] == p[1])
{
count++;
p++;
}
int n = 0;
while (count > 0)
{
n += count % 10;
count /= 10;
}
while (n > 0)
{
*q++ = (n % 10) + '0';
n /= 10;
}
*q++ = p[0];
p++;
}
*q = '\0';
}
static char *countAndSay(int n)
{
if (n < 1)
{
return NULL;
}
char *result;
char *prev = malloc(10000);
char *next = malloc(10000);
strcpy(prev, "1");
if (n == 1)
{
return prev;
}
int i;
for (i = 2; i <= n; i++)
{
if (i & 0x1)
{
parse(next, prev);
result = prev;
}
else
{
parse(prev, next);
result = next;
}
}
return result;
}
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: ./test n\n");
exit(-1);
}
printf("%s\n", countAndSay(atoi(argv[1])));
return 0;
}
反转链表 II
给你单链表的头指针 head
和两个整数 left
和 right
,其中 left <= right
。请你反转从位置 left
到位置 right
的链表节点,返回反转后的链表。
示例 1
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
示例 2
输入:head = [5], left = 1, right = 1
输出:[5]
提示
- 链表中节点数目为
n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
进阶
你可以使用一趟扫描完成反转吗?
#include <stdio.h>
#include <stdlib.h>
struct ListNode
{
int val;
struct ListNode *next;
};
static struct ListNode *reverseBetween(struct ListNode *head, int m, int n)
{
int i;
struct ListNode dummy;
struct ListNode *prev = &dummy;
prev->next = head;
for (i = 1; i < m; i++)
{
prev = prev->next;
}
struct ListNode *p = prev->next;
for (i = m; i < n; i++)
{
struct ListNode *q = p->next;
p->next = q->next;
q->next = prev->next;
prev->next = q;
}
return dummy.next;
}
int main(int argc, char **argv)
{
if (argc < 3)
{
fprintf(stderr, "Usage: ./test m n 1 2 3...\n");
exit(-1);
}
int i, count = argc - 3;
struct ListNode dummy;
struct ListNode *prev = &dummy;
struct ListNode *p;
for (i = 0; i < count; i++)
{
p = malloc(sizeof(*p));
p->val = atoi(argv[i + 3]);
p->next = NULL;
prev->next = p;
prev = p;
}
int m = atoi(argv[1]);
int n = atoi(argv[2]);
struct ListNode *head = reverseBetween(dummy.next, m, n);
for (p = head; p != NULL; p = p->next)
{
printf("%d ", p->val);
}
printf("\n");
return 0;
}
文本对齐
给定一个单词数组和一个长度 maxWidth
,重新排版单词,使其成为每行恰好有 maxWidth
个字符,且左右两端对齐的文本。
你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' '
填充,使得每行恰好有 maxWidth
个字符。
要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
文本的最后一行应为左对齐,且单词之间不插入额外的空格。
说明
- 单词是指由非空格字符组成的字符序列。
- 每个单词的长度大于 0,小于等于
maxWidth
。 - 输入单词数组
words
至少包含一个单词。
示例 1
输入:
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16
输出:
[
"This is an",
"example of text",
"justification. "
]
示例 2
输入:
words = ["What","must","be","acknowledgment","shall","be"]
maxWidth = 16
输出:
[
"What must be",
"acknowledgment ",
"shall be "
]
解释: 注意最后一行的格式应为 "shall be " 而不是 “shall be”
因为最后一行应为左对齐,而不是左右两端对齐,第二行同样为左对齐,这是因为这行只包含一个单词。
示例 3
输入:
words = ["Science","is","what","we","understand","well","enough","to","explain",
"to","a","computer.","Art","is","everything","else","we","do"]
maxWidth = 20
输出:
[
"Science is what we",
"understand well",
"enough to explain to",
"a computer. Art is",
"everything else we",
"do "
]
以下是填写空白处内容的示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void line_fill(char *line, int len, char **words, int *word_lens, int max_size,
int even_spaces, int remain_spaces, int start, int end)
{
int i, j;
char *p = line;
for (i = start; i < end; i++)
{
memcpy(p, words[i], word_lens[i]);
p += word_lens[i];
if (i < end - 1)
{
for (j = 0; j < even_spaces; j++)
{
*p++ = ' ';
}
if (remain_spaces > 0)
{
*p++ = ' ';
remain_spaces--;
}
}
}
while (p - line < max_size)
{
*p++ = ' ';
}
*p++ = '\0';
}
static char **fullJustify(char **words, int wordsSize, int maxWidth, int *returnSize)
{
int i, j, k, cap = 100, count = 0;
char **lines = malloc(cap * sizeof(char *));
char *buf = malloc(cap * (maxWidth + 1));
for (i = 0; i < cap; i++)
{
lines[i] = buf + i * (maxWidth + 1);
}
int *word_lens = malloc(wordsSize * sizeof(int));
for (i = 0; i < wordsSize; i++)
{
word_lens[i] = strlen(words[i]);
}
int wc = 0;
int len = 0;
int start = 0;
int chars = 0;
for (i = 0, j = 0; i < wordsSize; i++)
{
if (len + word_lens[i] > maxWidth)
{
int even_spaces = wc == 1 ? 0 : (maxWidth - chars) / (wc - 1);
int remain_spaces = wc == 1 ? 0 : (maxWidth - chars) % (wc - 1);
line_fill(lines[count], len, words, word_lens, maxWidth, even_spaces, remain_spaces, start, i);
count++;
wc = 1;
len = word_lens[i] + 1;
chars = word_lens[i];
start = i;
}
else if (len + word_lens[i] == maxWidth)
{
chars += word_lens[i];
int even_spaces = wc == 0 ? 0 : (maxWidth - chars) / wc;
int remain_spaces = wc == 0 ? 0 : (maxWidth - chars) % wc;
line_fill(lines[count], len, words, word_lens, maxWidth, even_spaces, remain_spaces, start, i + 1);
count++;
wc = 0;
len = 0;
chars = 0;
start = i + 1;
}
else
{
chars += word_lens[i];
len += word_lens[i] + 1;
wc++;
}
}
if (wc > 0)
{
char *p = lines[count];
for (i = start; i < start + wc; i++)
{
memcpy(p, words[i], word_lens[i]);
p += word_lens[i];
if (i < start + wc - 1)
{
*p++ = ' ';
}
}
while (p - lines[count] < maxWidth)
{
*p++ = ' ';
}
*p++ = '\0';
count++;
}
*returnSize = count;
return lines;
}
int main(int argc, char **argv)
{
if (argc <= 2)
{
fprintf(stderr, "Usage: ./test maxsize words...\n");
exit(-1);
}
int i, count;
char **lines = fullJustify(argv + 2, argc - 2, atoi(argv[1]), &count);
for (i = 0; i < count; i++)
{
printf("%s\n", lines[i]);
}
return 0;
}