qidao123.com技术社区-IT企服评测·应用市场
标题:
leetcode热题100(2)
[打印本页]
作者:
嚴華
时间:
2025-4-27 00:16
标题:
leetcode热题100(2)
leetcode-73-矩阵置零
法一:两个标记数组分别记录每一行和每一列是否有零出现
时间复杂度O(mn) 空间复杂度O(m+n)
void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
int m = matrixSize;
int n = matrixColSize[0];
int row[m], col[n];
memset(row, 0, sizeof(row));
memset(col, 0, sizeof(col));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!matrix[i][j]) {
row[i] = col[j] = true;
}
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (row[i] || col[j]) {
matrix[i][j] = 0;
}
}
}
}
复制代码
法二:使用两个标记量
可以用矩阵的第一行和第一列取代方法一中的两个标记数组,以达到O(!)的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包罗0,因此需要额外使用两个标记量分别记录第一行和第一列是否原本包罗0
时间复杂度O(mn) 空间复杂度O(1)
void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {
int m = matrixSize;
int n = matrixColSize[0];
int flag_col0 = false, flag_row0 = false;
for(int i = 0 ; i < m ; i++){
if(!matrix[i][0])
flag_col0 = true;
}
for(int j = 0 ; j < n ; j++){
if(!matrix[0][j])
flag_row0 = true;
}
for(int i = 1 ; i < m ; i++){
for(int j = 1 ; j < n ; j++){
if(!matrix[i][j])
matrix[i][0] = matrix[0][j] = 0;
}
}
for(int i = 1 ; i < m ; i++){
for(int j = 1 ; j < n ; j++){
if(!matrix[i][0] || !matrix[0][j])
matrix[i][j] = 0;
}
}
if(flag_col0){
for(int i = 0 ; i < m ;i++){
matrix[i][0] = 0;
}
}
if(flag_row0){
for(int j = 0 ; j < n ; j++){
matrix[0][j] = 0;
}
}
}
复制代码
leetcode-48-旋转图像
转置+按列翻转
void rotate(int** matrix, int matrixSize, int* matrixColSize) {
int temp;
int n = matrixSize;
for(int i = 0 ; i < n ; i++){
for(int j = i ; j < n ; j++){
if(i == j) continue;
temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
for(int j = 0 ; j < n/2 ; j++){
for(int i = 0 ; i< n ; i++){
temp = matrix[i][j];
matrix[i][j] = matrix[i][n-j-1];
matrix[i][n-j-1] = temp;
}
}
}
复制代码
leetcode-240-搜刮二维矩阵II
1.二分查找
由于矩阵每行都是升序的,所以可以依次遍历每行进行二分查找
时间O(mlogn) 空间O(1)
int binarySearch(int* nums, int size, int target){
int l = 0, r = size-1;
while(l <= r){
int mid = (l+r)/2;
if(nums[mid] > target){
r = mid-1;
}
else if(nums[mid] < target){
l = mid+1;
}
else{
return mid;
}
}
return -1;
}
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
int index;
for(int i = 0; i < matrixSize ; i++){
index = binarySearch(matrix[i],matrixColSize[i],target);
if(index >= 0)
return true;
}
return false;
}
复制代码
2.Z字形查找
从矩阵右上角matrix
[j]开始探求
若matrix
[j] > target 列--
若matrix
[j] < target 行++
时间O(m+n) 空间O(1)
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {
int m = matrixSize, n = matrixColSize[0];
int i = 0, j = n - 1;
while (i < m && j >= 0) {
if (matrix[i][j] == target) {
return true;
}
if (matrix[i][j] < target) {
i++;
} else {
j--;
}
}
return false;
}
复制代码
leetcode-160-相交链表
1.两个链表相交
设headA和headB的长度分别是m和n。假设headA不相交部分有a个节点,headB不相交部分有b个节点,两个链表相交部分有c个节点,则 a+c = m, b+c = n
(1)若a = b,则两个指针会同时到达两个链表相交部分,此时返回相交节点
(2)若a 不等于 b,则指针pA遍历完headA,然后指向headB,指针pB遍历完headB,然后指向headA,然后两个指针继续移动,在指针pA移动了a+c+b次,指针pB移动了b+c+a次之后,两个指针会同时达到相交节点
2.两个链表不相交
设headA和headB的长度分别是m和n。考虑当m等于n 和 m不等于n
(1)若m 等于 n,则两个指针会同时到达链尾,返回NULL
(2)若m 不等于 n,由于链表没有公共节点,两个指针不会同时到达链尾,因此两个指针都会遍历完两个链表,在指针pA移动了m+n次,指针pB移动了n+m次后,两个指针都会同时变为NULL
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA == NULL || headB == NULL)
return NULL;
struct ListNode *pA = headA, *pB = headB;
while(pA != pB){
pA = pA == NULL ? headB : pA->next;
pB = pB == NULL ? headA : pB->next;
}
return pA;
}
复制代码
2.getLen求不带头结点的链表长度
int getLen(struct ListNode* head){
int len = 1;
struct ListNode* p = head;
while(p != NULL){
p = p->next;
len++;
}
return len;
}
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int lenA = getLen(headA);
int lenB = getLen(headB);
struct ListNode *pA, *pB;
for(pA = headA ; lenA > lenB ; lenA--){
pA = pA->next;
}
for(pB = headB ; lenA < lenB ; lenB--){
pB = pB->next;
}
while(pA != NULL && pA != pB){
pA = pA->next;
pB = pB->next;
}
return pA;
}
复制代码
leetcode-234-回文链表
双指针:
找到链表的中间结点,将链表的后半部分翻转后,再从链表中间结点开始,与链头两两相比较,若不相同,则返回false
bool isPalindrome(struct ListNode* head) {
if(head == NULL)
return true;
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
dummy->next = head;
struct ListNode *p = dummy, *q = dummy;
while(q != NULL && q->next != NULL){
p = p->next;
q = q->next->next;
}
//将链表从中间断开 q指向后半部分的头部 p指向前半部分尾部
q = p->next;
p->next = NULL;
//将后半部分翻转
while(q != NULL){
struct ListNode* tmp = q->next;
q->next = p->next;
p->next = q;
q = tmp;
}
//前后开始两两比较
q = p->next;
p = dummy->next;
while(q != NULL){
if(p->val != q->val)
return false;
p = p->next;
q = q->next;
}
return true;
}
复制代码
leetcode-21-归并两个有序链表
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
if (list1 == NULL || list2 == NULL)
return list1 != NULL ? list1 : list2;
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *tmp, *tmp1;
struct ListNode *p, *q;
if(list1->val > list2->val){
tmp = list1;
list1 = list2;
list2 = tmp;
}
dummy->next = list1;
p = dummy;
q = list2;
while(p != NULL && q != NULL){
while(p->next != NULL && p->next->val < q->val){
p = p->next;
}
tmp = p->next;
p->next =q;
p = q;
q = tmp;
}
return dummy->next;
}
复制代码
2.
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
if(list1 == NULL || list2 == NULL)
return list1 != NULL ? list1 : list2;
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *pre, *p, *q;
pre = dummy;
p = list1;
q = list2;
while(p != NULL && q != NULL){
if(p->val <= q->val){
pre->next =p;
pre =pre->next;
p = p->next;
}
else if(p->val > q->val){
pre->next = q;
pre = pre->next;
q = q->next;
}
}
if(p != NULL){
pre->next = p;
}
if(q != NULL){
pre->next = q;
}
return dummy->next;
}
复制代码
leetcode-25-k个一组翻转链表
struct ListNode* move(struct ListNode* node, int n){
while(node != NULL && n > 0){
node = node->next;
n--;
}
return node;
}
struct ListNode* reverseKGroup(struct ListNode* head, int k) {
struct ListNode *p, *q, *pre, *tmp, *link;
bool flag = true;
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
dummy->next = head;
p = q = link = dummy->next;
while(q != NULL){
q = move(q,k-1);
if(q == NULL)
break;
pre = q->next;
while(pre != q){
tmp = p->next;
p->next = pre;
pre = p;
p = tmp;
}
if(flag){
dummy->next = q;
flag = false;
}else{
link->next = q;
}
link = q;
link = move(link,k-1);
q = p;
}
return dummy->next;
}
复制代码
2.k一组翻转
3.用栈
leetcode-2-两数相加
考虑以下环境:
1.list1 比 list2 长 list2相加完后仍有进位
2.list2 比 list1 长 list1相加完后仍有进位
3.list1 和 list2 一样长,相加完后仍有进位
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
int count;
struct ListNode *p, *q, *pre;
struct ListNode *dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
count = 0;
p = l1, q = l2, pre = dummy;
while(p != NULL || q != NULL){
struct ListNode *node = (struct ListNode*)malloc(sizeof(struct ListNode));
node->next = NULL;
int n1 = p != NULL ? p->val : 0;
int n2 = q != NULL ? q->val : 0;
node->val = (n1 + n2 + count)%10;
count = (n1 + n2 + count)/10;
pre->next = node;
pre = node;
if(p != NULL){
p = p->next;
}
if(q != NULL){
q = q->next;
}
}
if(count != 0){
struct ListNode *node = (struct ListNode*)malloc(sizeof(struct ListNode));
node->next = NULL;
node->val = count;
pre->next = node;
}
return dummy->next;
}
复制代码
leetcode-138-随机链表的复制
leetcode-148-排序链表
归并法
struct ListNode* middleNode(struct ListNode* head) {
struct ListNode* pre = head;
struct ListNode* slow = head;
struct ListNode* fast = head;
while (fast && fast->next) {
pre = slow;
slow = slow->next;
fast = fast->next->next;
}
pre->next = NULL;
return slow;
}
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
struct ListNode dummy;
struct ListNode* cur = &dummy;
while (list1 && list2) {
if (list1->val < list2->val) {
cur->next = list1;
list1 = list1->next;
} else {
cur->next = list2;
list2 = list2->next;
}
cur = cur->next;
}
cur->next = list1 ? list1 : list2;
return dummy.next;
}
struct ListNode* sortList(struct ListNode* head) {
if (head == NULL || head->next == NULL) {
return head;
}
struct ListNode* head2 = middleNode(head);
head = sortList(head);
head2 = sortList(head2);
return mergeTwoLists(head, head2);
}
复制代码
leetcode-23-归并k个升序链表
leetcode-146-LRU缓存
leetcode-543-二叉树的直径
一条路径的长度为该路径经过的节点数减一,所以求直径(即求路径长度的最大值)等效于求路径经过节点数的最大值减一。
而恣意一条路径均可以被看作由某个节点为出发点,从其左儿子和右儿子向下遍历的路径拼接得到
假设我们知道对于该节点的左儿子向下遍历经过最多的节点数 L (即以左儿子为根的子树的深度) 和其右儿子向下遍历经过最多的节点数 R (即以右儿子为根的子树的深度),那么以该节点为出发点的路径经过节点数的最大值即为 L+R+1 。
二叉树的
最大深度
是指从根节点到最远叶子节点的最长路径上的节点数。
int getDeep(struct TreeNode* root, int* ans){
if(root == NULL)
return 0;
int left = getDeep(root->left,ans);
int right = getDeep(root->right,ans);
*ans = fmax(*ans,left+right+1);
return fmax(left,right)+1;
}
int diameterOfBinaryTree(struct TreeNode* root) {
int ans = 1;
getDeep(root,&ans);
return ans-1;
}
复制代码
leetcode-662-二叉树最大宽度
leetcode-124-二叉树最大路径和
leetcode-437-路径总和III
leetcode-230-二叉搜刮树第k小元素
int kthSmallest(struct TreeNode* root, int k) {
struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*)*10000);
int* res = (int*)malloc(sizeof(int)*10000);
struct TreeNode* node = root;
int stk_top = 0;
int index = 0;
while(node != NULL || stk_top > 0){
while(node != NULL){
stk[stk_top++] = node;
node = node->left;
}
node = stk[--stk_top];
res[index++] = node->val;
node = node->right;
}
return res[k-1];
}
复制代码
leetcode-144-二叉树睁开为链表
void flatten(struct TreeNode* root) {
struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*)*10000);
struct TreeNode** res = (struct TreeNode**)malloc(sizeof(struct TreeNode*)*10000);
int stk_top, index;
stk_top = 0, index = 0;
struct TreeNode* node = root;
while(node != NULL || stk_top > 0){
while(node != NULL){
stk[stk_top++] = node;
res[index++] = node;
node = node->left;
}
node = stk[--stk_top];
node = node->right;
}
for(int i = 0 ; i < index ; i++){
res[i]->left = NULL;
res[i]->right = NULL;
}
for(int i = 0 ; i < index-1 ; i++){
res[i]->right = res[i+1];
}
}
复制代码
leetcode-124-二叉树中最大路径和
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/)
Powered by Discuz! X3.4