文章目錄
- 題目一:盛最多水的容器
- 題目描述:
- 題目分析:
- 解題思路:
- 示例代碼:
- 深入剖析:
- 題目二:最長無重復字符的子串
- 題目描述:
- 題目分析:
- 解題思路:
- 示例代碼:
- 深入剖析:
- 題目三:合并區間
- 題目描述:
- 題目分析:
- 解題思路:
- 示例代碼:
- 深入剖析:
🌈你好呀!我是 山頂風景獨好
🎈歡迎踏入我的博客世界,能與您在此邂逅,真是緣分使然!😊
🌸愿您在此停留的每一刻,都沐浴在輕松愉悅的氛圍中。
📖這里不僅有豐富的知識和趣味橫生的內容等您來探索,更是一個自由交流的平臺,期待您留下獨特的思考與見解。🌟
🚀讓我們一起踏上這段探索與成長的旅程,攜手挖掘更多可能,共同進步!💪?
題目一:盛最多水的容器
題目描述:
給定 n 個非負整數 a1,a2,…,an,每個數代表一個坐標點 (i, ai) 。在坐標內畫 n 條垂直線,使得 i 垂直線的兩個端點分別為 (i, ai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸構成的容器可以容納最多的水。
題目分析:
這是一個典型的雙指針問題。我們可以使用兩個指針分別指向數組的首尾,然后計算當前兩個指針所構成的容器的面積。接著,我們移動指向較短線段的指針(因為容器的高度由較短的線段決定,移動較長線段的指針無法增加容器的高度,而只會減少容器的寬度),直到兩個指針相遇。
解題思路:
初始化兩個指針,一個指向數組的開始,另一個指向數組的末尾。
計算當前兩個指針所構成的容器的面積,并更新最大面積。
移動指向較短線段的指針。
重復步驟2和3,直到兩個指針相遇。
返回最大面積。
示例代碼:
#include <stdio.h> // 函數聲明
int maxArea(int* height, int heightSize); int main() { int height[] = {1,8,6,2,5,4,8,3,7}; int heightSize = sizeof(height) / sizeof(height[0]); int result = maxArea(height, heightSize); printf("Maximum area: %d\n", result); return 0;
} // 計算最大容器面積的函數實現
int maxArea(int* height, int heightSize) { int max_area = 0; int left = 0; int right = heightSize - 1; while (left < right) { // 計算當前容器的面積 int current_area = (right - left) * ((height[left] < height[right]) ? height[left] : height[right]); // 更新最大面積 if (current_area > max_area) { max_area = current_area; } // 移動指向較短線段的指針 if (height[left] < height[right]) { left++; } else { right--; } } return max_area;
}
深入剖析:
該算法的時間復雜度為O(n),因為我們只遍歷了數組一次。空間復雜度為O(1),因為我們只使用了常數級別的額外空間。這種雙指針的技巧在處理類似問題時非常有用,特別是當問題涉及到數組或鏈表的兩端時。
題目二:最長無重復字符的子串
題目描述:
給定一個字符串,找出其中沒有重復字符的最長子串的長度。
題目分析:
這是一個滑動窗口問題。我們可以使用兩個指針來定義一個窗口,窗口內的字符都是唯一的。當遇到重復字符時,我們移動左指針來縮小窗口,直到窗口內沒有重復字符為止。同時,我們需要一個哈希表來記錄每個字符在窗口中的位置,以便在O(1)時間內判斷字符是否重復。
解題思路:
初始化兩個指針(left和right)和一個哈希表(用于記錄字符的位置)。
使用right指針擴展窗口,直到遇到重復字符。
當遇到重復字符時,移動left指針縮小窗口,直到窗口內沒有重復字符。
在每次移動窗口后,更新最大長度。
重復步驟2-4,直到right指針到達字符串的末尾。
返回最大長度。
示例代碼:
#include <stdio.h>
#include <string.h> // 函數聲明
int lengthOfLongestSubstring(char * s); int main() { char s[] = "abcabcbb"; int result = lengthOfLongestSubstring(s); printf("Length of longest substring without repeating characters: %d\n", result); return 0;
} // 計算最長無重復字符子串長度的函數實現
int lengthOfLongestSubstring(char * s) { int n = strlen(s); if (n == 0) { return 0; } int max_len = 0; int left = 0; int right = 0; int char_map[256] = { -1 }; // 假設輸入字符為ASCII碼 while (right < n) { if (char_map[s[right]] != -1) { // 遇到重復字符,移動左指針 left = (char_map[s[right]] + 1 > left) ? char_map[s[right]] + 1 : left; } // 更新字符的位置 char_map[s[right]] = right; // 更新最大長度 max_len = (right - left + 1 > max_len) ? right - left + 1 : max_len; // 移動右指針 right++; } return max_len;
}
深入剖析:
該算法的時間復雜度為O(n),因為我們只遍歷了字符串一次。空間復雜度為O(1)(如果考慮哈希表的大小為常數,因為ASCII碼字符集是有限的),但實際上哈希表的大小取決于字符集的大小,對于Unicode字符集,空間復雜度會稍大一些。滑動窗口技巧在處理子串、子數組相關問題時非常有效。
題目三:合并區間
題目描述:
給出一個區間的集合,請合并所有重疊的部分。
題目分析:
這是一個排序和合并問題。首先,我們需要對區間按照起始位置進行排序。然后,我們遍歷排序后的區間列表,使用一個變量來跟蹤當前的合并區間。如果下一個區間的起始位置小于或等于當前合并區間的結束位置,則將它們合并;否則,將當前合并區間添加到結果列表中,并更新合并區間為下一個區間。
解題思路:
對區間按照起始位置進行排序。
初始化一個空的結果列表和一個變量來跟蹤當前的合并區間。
遍歷排序后的區間列表:
如果當前區間與合并區間重疊,則合并它們。
否則,將合并區間添加到結果列表中,并更新合并區間為當前區間。
將最后一個合并區間添加到結果列表中。
返回結果列表。
示例代碼:
#include <stdio.h>
#include <stdlib.h> // 區間結構體定義
typedef struct { int start; int end;
} Interval; // 比較函數,用于qsort排序
int compare(const void *a, const void *b) { Interval *intervalA = (Interval *)a; Interval *intervalB = (Interval *)b; return intervalA->start - intervalB->start;
} // 合并區間的函數聲明
Interval* merge(Interval* intervals, int intervalsSize, int* returnSize); int main() { Interval intervals[] = {{1, 3}, {2, 6}, {8, 10}, {15, 18}}; int intervalsSize = sizeof(intervals) / sizeof(intervals[0]); int returnSize = 0; Interval* result = merge(intervals, intervalsSize, &returnSize); printf("Merged intervals:\n"); for (int i = 0; i < returnSize; i++) { printf("[%d, %d] ", result[i].start, result[i].end); } printf("\n"); // 釋放動態分配的內存 free(result); return 0;
} // 合并區間的函數實現
Interval* merge(Interval* intervals, int intervalsSize, int* returnSize) { if (intervalsSize == 0) { *returnSize = 0; return NULL; } // 按照起始位置排序區間 qsort(intervals, intervalsSize, sizeof(Interval), compare); // 動態分配結果數組的內存 Interval* merged = (Interval*)malloc(intervalsSize * sizeof(Interval)); *returnSize = 0; // 初始化當前合并區間 Interval current = intervals[0]; for (int i = 1; i < intervalsSize; i++) { if (intervals[i].start <= current.end) { // 當前區間與合并區間重疊,合并它們 current.end = (intervals[i].end > current.end) ? intervals[i].end : current.end; } else { // 當前區間與合并區間不重疊,將合并區間添加到結果列表中,并更新合并區間 merged[*returnSize] = current; (*returnSize)++; current = intervals[i]; } } // 添加最后一個合并區間到結果列表中 merged[*returnSize] = current; (*returnSize)++; return merged;
}
深入剖析:
該算法的時間復雜度為O(n log n),其中n是區間的數量,因為我們需要對區間進行排序。空間復雜度為O(n),因為我們需要動態分配一個與區間數量相等大小的結果數組。合并區間的技巧在處理類似問題時非常有用,特別是當問題涉及到重疊區間的合并、求并集等操作時。
? 這就是今天要分享給大家的全部內容了,我們下期再見!😊
🏠 我在CSDN等你哦!我的主頁😍