diff --git a/solution/3500-3599/3599.Partition Array to Minimize XOR/README.md b/solution/3500-3599/3599.Partition Array to Minimize XOR/README.md index cbcbec1a0f143..5a4e51232378f 100644 --- a/solution/3500-3599/3599.Partition Array to Minimize XOR/README.md +++ b/solution/3500-3599/3599.Partition Array to Minimize XOR/README.md @@ -98,32 +98,162 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3500-3599/3599.Pa -### 方法一 +### 方法一:动态规划 + +我们定义 $f[i][j]$ 表示将前 $i$ 个元素划分成 $j$ 个子数组的最大 XOR 的最小值。初始时 $f[0][0] = 0$,其余 $f[i][j] = +\infty$。 + +为了快速计算子数组的 XOR,我们可以使用前缀 XOR 数组 $g$,其中 $g[i]$ 表示前 $i$ 个元素的 XOR 值,那么对于子数组 $[h + 1...i]$(下标从 $1$ 开始),其 XOR 值为 $g[i] \oplus g[h]$。 + +接下来,我们在 $[1, n]$ 的范围内遍历 $i$,在 $[1, \min(i, k)]$ 的范围内遍历 $j$,并在 $[j - 1, i - 1]$ 的范围内遍历 $h$,其中 $h$ 表示上一个子数组的结束位置(下标从 $1$ 开始)。我们可以通过以下状态转移方程来更新 $f[i][j]$: + +$$ +f[i][j] = \min_{h \in [j - 1, i - 1]} \max(f[h][j - 1], g[i] \oplus g[h]) +$$ + +最后,我们返回 $f[n][k]$,即将整个数组划分成 $k$ 个子数组的最大 XOR 的最小值。 + +时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times k)$,其中 $n$ 是数组的长度。 #### Python3 ```python - +min = lambda a, b: a if a < b else b +max = lambda a, b: a if a > b else b + + +class Solution: + def minXor(self, nums: List[int], k: int) -> int: + n = len(nums) + g = [0] * (n + 1) + for i, x in enumerate(nums, 1): + g[i] = g[i - 1] ^ x + + f = [[inf] * (k + 1) for _ in range(n + 1)] + f[0][0] = 0 + for i in range(1, n + 1): + for j in range(1, min(i, k) + 1): + for h in range(j - 1, i): + f[i][j] = min(f[i][j], max(f[h][j - 1], g[i] ^ g[h])) + return f[n][k] ``` #### Java ```java - +class Solution { + public int minXor(int[] nums, int k) { + int n = nums.length; + int[] g = new int[n + 1]; + for (int i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + int[][] f = new int[n + 1][k + 1]; + for (int i = 0; i <= n; ++i) { + Arrays.fill(f[i], Integer.MAX_VALUE); + } + f[0][0] = 0; + + for (int i = 1; i <= n; ++i) { + for (int j = 1; j <= Math.min(i, k); ++j) { + for (int h = j - 1; h < i; ++h) { + f[i][j] = Math.min(f[i][j], Math.max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int minXor(vector& nums, int k) { + int n = nums.size(); + vector g(n + 1); + for (int i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + const int inf = numeric_limits::max(); + vector f(n + 1, vector(k + 1, inf)); + f[0][0] = 0; + + for (int i = 1; i <= n; ++i) { + for (int j = 1; j <= min(i, k); ++j) { + for (int h = j - 1; h < i; ++h) { + f[i][j] = min(f[i][j], max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; + } +}; ``` #### Go ```go +func minXor(nums []int, k int) int { + n := len(nums) + g := make([]int, n+1) + for i := 1; i <= n; i++ { + g[i] = g[i-1] ^ nums[i-1] + } + + const inf = math.MaxInt32 + f := make([][]int, n+1) + for i := range f { + f[i] = make([]int, k+1) + for j := range f[i] { + f[i][j] = inf + } + } + f[0][0] = 0 + + for i := 1; i <= n; i++ { + for j := 1; j <= min(i, k); j++ { + for h := j - 1; h < i; h++ { + f[i][j] = min(f[i][j], max(f[h][j-1], g[i]^g[h])) + } + } + } + + return f[n][k] +} +``` +#### TypeScript + +```ts +function minXor(nums: number[], k: number): number { + const n = nums.length; + const g: number[] = Array(n + 1).fill(0); + for (let i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + const inf = Number.MAX_SAFE_INTEGER; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(inf)); + f[0][0] = 0; + + for (let i = 1; i <= n; ++i) { + for (let j = 1; j <= Math.min(i, k); ++j) { + for (let h = j - 1; h < i; ++h) { + f[i][j] = Math.min(f[i][j], Math.max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; +} ``` diff --git a/solution/3500-3599/3599.Partition Array to Minimize XOR/README_EN.md b/solution/3500-3599/3599.Partition Array to Minimize XOR/README_EN.md index 0f1175d45faeb..533f5541023c3 100644 --- a/solution/3500-3599/3599.Partition Array to Minimize XOR/README_EN.md +++ b/solution/3500-3599/3599.Partition Array to Minimize XOR/README_EN.md @@ -95,32 +95,162 @@ A subarray is a contiguous non-empty sequence of element -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j]$ as the minimum possible value of the maximum XOR among all ways to partition the first $i$ elements into $j$ subarrays. Initially, set $f[0][0] = 0$, and all other $f[i][j] = +\infty$. + +To quickly compute the XOR of a subarray, we can use a prefix XOR array $g$, where $g[i]$ represents the XOR of the first $i$ elements. For the subarray $[h + 1...i]$ (with indices starting from $1$), its XOR value is $g[i] \oplus g[h]$. + +Next, we iterate $i$ from $1$ to $n$, $j$ from $1$ to $\min(i, k)$, and $h$ from $j - 1$ to $i - 1$, where $h$ represents the end position of the previous subarray (indices starting from $1$). We update $f[i][j]$ using the following state transition equation: + +$$ +f[i][j] = \min_{h \in [j - 1, i - 1]} \max(f[h][j - 1], g[i] \oplus g[h]) +$$ + +Finally, we return $f[n][k]$, which is the minimum possible value of the maximum XOR when partitioning the entire array into $k$ subarrays. + +The time complexity is $O(n^2 \times k)$, and the space complexity is $O(n \times k)$, where $n$ is the length of the array. #### Python3 ```python - +min = lambda a, b: a if a < b else b +max = lambda a, b: a if a > b else b + + +class Solution: + def minXor(self, nums: List[int], k: int) -> int: + n = len(nums) + g = [0] * (n + 1) + for i, x in enumerate(nums, 1): + g[i] = g[i - 1] ^ x + + f = [[inf] * (k + 1) for _ in range(n + 1)] + f[0][0] = 0 + for i in range(1, n + 1): + for j in range(1, min(i, k) + 1): + for h in range(j - 1, i): + f[i][j] = min(f[i][j], max(f[h][j - 1], g[i] ^ g[h])) + return f[n][k] ``` #### Java ```java - +class Solution { + public int minXor(int[] nums, int k) { + int n = nums.length; + int[] g = new int[n + 1]; + for (int i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + int[][] f = new int[n + 1][k + 1]; + for (int i = 0; i <= n; ++i) { + Arrays.fill(f[i], Integer.MAX_VALUE); + } + f[0][0] = 0; + + for (int i = 1; i <= n; ++i) { + for (int j = 1; j <= Math.min(i, k); ++j) { + for (int h = j - 1; h < i; ++h) { + f[i][j] = Math.min(f[i][j], Math.max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; + } +} ``` #### C++ ```cpp - +class Solution { +public: + int minXor(vector& nums, int k) { + int n = nums.size(); + vector g(n + 1); + for (int i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + const int inf = numeric_limits::max(); + vector f(n + 1, vector(k + 1, inf)); + f[0][0] = 0; + + for (int i = 1; i <= n; ++i) { + for (int j = 1; j <= min(i, k); ++j) { + for (int h = j - 1; h < i; ++h) { + f[i][j] = min(f[i][j], max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; + } +}; ``` #### Go ```go +func minXor(nums []int, k int) int { + n := len(nums) + g := make([]int, n+1) + for i := 1; i <= n; i++ { + g[i] = g[i-1] ^ nums[i-1] + } + + const inf = math.MaxInt32 + f := make([][]int, n+1) + for i := range f { + f[i] = make([]int, k+1) + for j := range f[i] { + f[i][j] = inf + } + } + f[0][0] = 0 + + for i := 1; i <= n; i++ { + for j := 1; j <= min(i, k); j++ { + for h := j - 1; h < i; h++ { + f[i][j] = min(f[i][j], max(f[h][j-1], g[i]^g[h])) + } + } + } + + return f[n][k] +} +``` +#### TypeScript + +```ts +function minXor(nums: number[], k: number): number { + const n = nums.length; + const g: number[] = Array(n + 1).fill(0); + for (let i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + const inf = Number.MAX_SAFE_INTEGER; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(inf)); + f[0][0] = 0; + + for (let i = 1; i <= n; ++i) { + for (let j = 1; j <= Math.min(i, k); ++j) { + for (let h = j - 1; h < i; ++h) { + f[i][j] = Math.min(f[i][j], Math.max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; +} ``` diff --git a/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.cpp b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.cpp new file mode 100644 index 0000000000000..7c7739e328216 --- /dev/null +++ b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.cpp @@ -0,0 +1,24 @@ +class Solution { +public: + int minXor(vector& nums, int k) { + int n = nums.size(); + vector g(n + 1); + for (int i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + const int inf = numeric_limits::max(); + vector f(n + 1, vector(k + 1, inf)); + f[0][0] = 0; + + for (int i = 1; i <= n; ++i) { + for (int j = 1; j <= min(i, k); ++j) { + for (int h = j - 1; h < i; ++h) { + f[i][j] = min(f[i][j], max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; + } +}; diff --git a/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.go b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.go new file mode 100644 index 0000000000000..9f25298572d04 --- /dev/null +++ b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.go @@ -0,0 +1,27 @@ +func minXor(nums []int, k int) int { + n := len(nums) + g := make([]int, n+1) + for i := 1; i <= n; i++ { + g[i] = g[i-1] ^ nums[i-1] + } + + const inf = math.MaxInt32 + f := make([][]int, n+1) + for i := range f { + f[i] = make([]int, k+1) + for j := range f[i] { + f[i][j] = inf + } + } + f[0][0] = 0 + + for i := 1; i <= n; i++ { + for j := 1; j <= min(i, k); j++ { + for h := j - 1; h < i; h++ { + f[i][j] = min(f[i][j], max(f[h][j-1], g[i]^g[h])) + } + } + } + + return f[n][k] +} \ No newline at end of file diff --git a/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.java b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.java new file mode 100644 index 0000000000000..8ca637fe4a790 --- /dev/null +++ b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.java @@ -0,0 +1,25 @@ +class Solution { + public int minXor(int[] nums, int k) { + int n = nums.length; + int[] g = new int[n + 1]; + for (int i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + int[][] f = new int[n + 1][k + 1]; + for (int i = 0; i <= n; ++i) { + Arrays.fill(f[i], Integer.MAX_VALUE); + } + f[0][0] = 0; + + for (int i = 1; i <= n; ++i) { + for (int j = 1; j <= Math.min(i, k); ++j) { + for (int h = j - 1; h < i; ++h) { + f[i][j] = Math.min(f[i][j], Math.max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; + } +} diff --git a/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.py b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.py new file mode 100644 index 0000000000000..8e563f18a7fb3 --- /dev/null +++ b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.py @@ -0,0 +1,18 @@ +min = lambda a, b: a if a < b else b +max = lambda a, b: a if a > b else b + + +class Solution: + def minXor(self, nums: List[int], k: int) -> int: + n = len(nums) + g = [0] * (n + 1) + for i, x in enumerate(nums, 1): + g[i] = g[i - 1] ^ x + + f = [[inf] * (k + 1) for _ in range(n + 1)] + f[0][0] = 0 + for i in range(1, n + 1): + for j in range(1, min(i, k) + 1): + for h in range(j - 1, i): + f[i][j] = min(f[i][j], max(f[h][j - 1], g[i] ^ g[h])) + return f[n][k] diff --git a/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.ts b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.ts new file mode 100644 index 0000000000000..2ed227df5d707 --- /dev/null +++ b/solution/3500-3599/3599.Partition Array to Minimize XOR/Solution.ts @@ -0,0 +1,21 @@ +function minXor(nums: number[], k: number): number { + const n = nums.length; + const g: number[] = Array(n + 1).fill(0); + for (let i = 1; i <= n; ++i) { + g[i] = g[i - 1] ^ nums[i - 1]; + } + + const inf = Number.MAX_SAFE_INTEGER; + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(inf)); + f[0][0] = 0; + + for (let i = 1; i <= n; ++i) { + for (let j = 1; j <= Math.min(i, k); ++j) { + for (let h = j - 1; h < i; ++h) { + f[i][j] = Math.min(f[i][j], Math.max(f[h][j - 1], g[i] ^ g[h])); + } + } + } + + return f[n][k]; +}