對於每個位置 i,我們可以直接計算其對應的位置 j=n−1−i,並交換 s[i] 和 s[j],其中 n 為陣列長度。
再來考慮 i 應該遍歷的範圍,由於我們是要將 s[i] 和 s[j] 交換,因此 i 只需要遍歷到 n/2−1 即可。
對於長度 n 為奇數的陣列,中間的元素不需要交換,因此枚舉到 n/2−1 即可。
對於長度 n 為偶數的陣列,最後一次交換發生在 (i,j)=(n/2−1,n/2),因此同樣也是枚舉到 n/2−1 即可。
複雜度分析
時間複雜度:O(n)
空間複雜度:O(1)
1 2 3 4 5 6 7 8
classSolution: defreverseString(self, s: List[str]) -> None: """ Do not return anything, modify s in-place instead. """ n = len(s) for i inrange(n//2): s[i], s[n-i-1] = s[n-i-1], s[i]
1 2 3 4 5 6 7
classSolution { public: voidreverseString(vector<char>& s){ int n = s.size(); for (int i = 0; i < n / 2; i++) swap(s[i], s[n - i - 1]); } };
寫法二:相向雙指標
上述方法中需要計算對應位置,並且需要稍微思考一下枚舉的範圍。另一種方法是使用兩個指標 i 和 j,分別指向陣列的頭尾,然後同時向中間移動,交換 s[i] 和 s[j],直到 i≥j 為止。或是換句話說,當 i<j 時,我們不斷交換 s[i] 和 s[j],並同時將 i 加一,j 減一。
複雜度分析
時間複雜度:O(n)
空間複雜度:O(1)
1 2 3 4 5 6 7 8 9 10
classSolution: defreverseString(self, s: List[str]) -> None: """ Do not return anything, modify s in-place instead. """ i, j = 0, len(s)-1 while i < j: s[i], s[j] = s[j], s[i] i += 1 j -= 1
1 2 3 4 5 6 7
classSolution { public: voidreverseString(vector<char>& s){ int i = 0, j = s.size() - 1; while (i < j) swap(s[i++], s[j--]); } };
寫在最後
Cover photo is generated by @たろたろ, thanks for their work!