Leetcode : Produk Tatasusunan Kecuali Diri
Masalah ini kelihatan mudah untuk diselesaikan dalam masa dan ruang linear. Masalah ini dibina berdasarkan beberapa konsep asas tatasusunan.
- Jalur lintasan.
- Jumlah Awalan dan Akhiran.
Syarikat yang telah bertanya perkara ini dalam temu bual pengekodan mereka ialah Facebook, Amazon, Apple, Netflix, Google, Microsoft, Adobe dan banyak lagi syarikat berteknologi tinggi.
Pernyataan masalah
Memandangkan nombor tatasusunan integer, kembalikan jawapan tatasusunan supaya jawapan[i] adalah sama dengan hasil darab semua elemen nombor kecuali nombor[i].
Produk mana-mana awalan atau akhiran nombor adalah dijamin untuk dimuatkan dalam 32-bit integer.
Anda mesti menulis algoritma yang berjalan dalam masa O(n) dan tanpa menggunakan operasi bahagi.
Kes ujian#1:
Input: nums = [1,2,3,4] Output: [24,12,8,6]
Kes ujian#2:
Input: nums = [-1,1,0,-3,3] Output: [0,0,9,0,0]
Memahami masalah
Masalah ini kelihatan lebih mudah untuk diselesaikan dalam masa dan ruang linear, tetapi ia adalah rumit apabila menulis pseudokod atau pelaksanaan kod sebenar.
Ilustrasi
Mari kita lihat hasil yang diharapkan daripada tatasusunan ringkas yang mengandungi 4 elemen:
input = {1, 2, 3, 4}
Jadi, nilai pada setiap indeks ialah hasil darab semua elemen lain dalam tatasusunan kecuali nilai itu sendiri. Rajah berikut menggambarkan ini.
Berdasarkan rajah di atas, kita boleh menghasilkan formula. Untuk sebarang indeks i tertentu, kita boleh mencari nilai menggunakan hasil darab unsur dari o hingga (i - 1) campur hasil darab unsur dari (i 1) hingga (N - 1). Ini digambarkan dalam rajah berikut:
Proses pemikiran
Sebelum menulis kod pseudo, buat soalan dan tanya penemuduga.
- Perlukah saya bimbang tentang pendua?
- Bagaimana jika tatasusunan kosong atau mempunyai satu elemen? Apakah hasil yang dijangkakan?
- Perlukah saya mempertimbangkan/mengabaikan nilai 0 dalam mana-mana indeks dalam tatasusunan? kerana semua nilai lain mendapat 0 kecuali indeks yang mengandungi 0.
- Apakah kes sudut/tepi untuk masalah ini?
Setelah anda dan penemuduga telah membincangkan soalan di atas, cipta pelbagai pendekatan untuk menyelesaikan masalah tersebut.
- Pendekatan naif/brute-force.
- Produk semua elemen.
- Produk Kiri dan Kanan.
- Imbuhan awalan dan akhiran.
Pendekatan 1: Naif/Brute-force
Intuisi
Untuk menggunakan pendekatan kekerasan, kita mesti melaksanakan dua gelung untuk. Apabila indeks gelung luar sepadan dengan nilai indeks gelung dalam, kita harus melangkau produk; jika tidak, kami meneruskan produk.
Algoritma
- Memulakan Pembolehubah:
- N = nums.length (panjang tatasusunan input).
- hasil = new int[N] (tatasusunan untuk menyimpan hasil).
- Gelung Luar (Lelar melalui setiap elemen dalam nombor):
- Untuk i = 0 hingga N-1:Memulakan semasaProduk = 1.
- Gelung Dalam (Kira produk untuk elemen semasa), untuk j = 0 hingga N-1:
- Jika i == j, langkau lelaran semasa menggunakan continue.
- DarabkanProduk semasa dengan nombor[j].
- TetapkanProduk semasa kepada hasil[i].
- Pulangan hasil.
Kod
// brute force static int[] bruteForce(int[] nums) { int N = nums.length; int[] result = new int[N]; for (int i = 0; i < N; i++) { int currentProduct = 1; for (int j = 0; j < N; j++) { if (i == j) { continue; } currentProduct *= nums[j]; } result[i] = currentProduct; } return result; }
Analisis kerumitan
- Kerumitan masa: O(n^2), untuk mengulang tatasusunan dua kali dalam gelung luar dan dalam.
- Kerumitan ruang: O(n), untuk ruang tambahan (tatasusunan hasil[]) yang kami gunakan.
Pendekatan 2: Produk tatasusunan ❌
Satu cara yang difikirkan oleh kebanyakan pembangun ialah menjalankan jumlah produk bagi semua elemen, membahagikan jumlah produk dengan setiap nilai tatasusunan dan mengembalikan hasilnya.
Pseudokod
// O(n) time and O(1) space p = 1 for i -> 0 to A[i] p * = A[i] for i -> 0 to (N - 1) A[i] = p/A[i] // if A[i] == 0 ? BAM error‼️
Kod
// code implementation static int[] productSum(int[] nums) { int product_sum = 1; for(int num: nums) { product_sum *= num; } for(int i = 0; i < nums.length; i++) { nums[i] = product_sum/nums[i]; } return nums; }
Bagaimana jika salah satu elemen tatasusunan mengandungi 0? ?
Nilai pada semua indeks kecuali indeks yang mengandungi 0 pasti akan menjadi infiniti. Selain itu, kod tersebut membuang java.lang.ArithmeticException.
Exception in thread "main" java.lang.ArithmeticException: / by zero at dev.ggorantala.ds.arrays.ProductOfArrayItself.productSum(ProductOfArrayItself.java:24) at dev.ggorantala.ds.arrays.ProductOfArrayItself.main(ProductOfArrayItself.java:14)
Pendekatan 3: Cari produk Awalan dan Akhiran
Ketahui lebih lanjut tentang jumlah awalan dan akhiran dalam Kursus Penguasaan Tatasusunan di tapak web saya https://ggorantala.dev
Intuisi & formula
Awalan dan Akhiran dikira sebelum menulis algoritma untuk hasilnya. Formula jumlah awalan dan akhiran diberikan di bawah:
Algorithm Steps
- Create an array result of the same length as nums to store the final results.
- Create two additional arrays prefix_sum and suffix_sum of the same length as nums.
- Calculate Prefix Products:
- Set the first element of prefix_sum to the first element of nums.
- Iterate through the input array nums starting from the second element (index 1). For each index i, set prefix_sum[i] to the product of prefix_sum[i-1] and nums[i].
- Calculate Suffix Products:
- Set the last element of suffix_sum to the last element of nums.
- Iterate through the input array nums starting from the second-to-last element (index nums.length - 2) to the first element. For each index i, set suffix_sum[i] to the product of suffix_sum[i+1] and nums[i].
- Calculate the result: Iterate through the input array nums.
- For the first element (i == 0), set result[i] to suffix_sum[i + 1].
- For the last element (i == nums.length - 1), set result[i] to prefix_sum[i - 1].
- For all other elements, set result[i] to the product of prefix_sum[i - 1] and suffix_sum[i + 1].
- Return the result array containing the product of all elements except the current element for each index.
Pseudocode
Function usingPrefixSuffix(nums): N = length of nums result = new array of length N prefix_sum = new array of length N suffix_sum = new array of length N // Calculate prefix products prefix_sum[0] = nums[0] For i from 1 to N-1: prefix_sum[i] = prefix_sum[i-1] * nums[i] // Calculate suffix products suffix_sum[N-1] = nums[N-1] For i from N-2 to 0: suffix_sum[i] = suffix_sum[i+1] * nums[i] // Calculate result array For i from 0 to N-1: If i == 0: result[i] = suffix_sum[i+1] Else If i == N-1: result[i] = prefix_sum[i-1] Else: result[i] = prefix_sum[i-1] * suffix_sum[i+1] Return result
Code
// using prefix and suffix arrays private static int[] usingPrefixSuffix(int[] nums) { int[] result = new int[nums.length]; int[] prefix_sum = new int[nums.length]; int[] suffix_sum = new int[nums.length]; // prefix sum calculation prefix_sum[0] = nums[0]; for (int i = 1; i < nums.length; i++) { prefix_sum[i] = prefix_sum[i - 1] * nums[i]; } // suffix sum calculation suffix_sum[nums.length - 1] = nums[nums.length - 1]; for (int i = nums.length - 2; i >= 0; i--) { suffix_sum[i] = suffix_sum[i + 1] * nums[i]; } for (int i = 0; i < nums.length; i++) { if (i == 0) { // when variable `i` is at 0th index result[i] = suffix_sum[i + 1]; } else if (i == nums.length - 1) { // when variable `i` is at last index result[i] = prefix_sum[i - 1]; } else { // for all other indexes result[i] = prefix_sum[i - 1] * suffix_sum[i + 1]; } } return result; }
Complexity analysis
-
Time complexity: The time complexity of the given code is O(n), where n is the length of the input array nums. This is because:
- Calculating the prefix_sum products take O(n) time.
- Calculating the suffix_sum products take O(n) time.
- Constructing the result array takes O(n) time.
Each of these steps involves a single pass through the array, resulting in a total time complexity of O(n)+O(n)+O(n) = 3O(n), which is O(n).
-
Space complexity: The space complexity of the given code is O(n). This is because:
- The prefix_sum array requires O(n) space.
- The suffix_sum array requires O(n) space.
- Theresult array requires O(n) space. All three arrays are of length n, so the total space complexity is O(n) + O(n) + O(n) = 3O(n), which is O(n).
Optimization ?
For the suffix array calculation, we override the input nums array instead of creating one.
private static int[] usingPrefixSuffixOptimization(int[] nums) { int[] result = new int[nums.length]; int[] prefix_sum = new int[nums.length]; // prefix sum calculation prefix_sum[0] = nums[0]; for (int i = 1; i < nums.length; i++) { prefix_sum[i] = prefix_sum[i - 1] * nums[i]; } // suffix sum calculation, in-place - `nums` array override for (int i = nums.length - 2; i >= 0; i--) { nums[i] = nums[i + 1] * nums[i]; } for (int i = 0; i < nums.length; i++) { if (i == 0) { // when variable `i` is at 0th index result[i] = nums[i + 1]; } else if (i == nums.length - 1) { // when variable `i` is at last index result[i] = prefix_sum[i - 1]; } else { // for all other indexes result[i] = prefix_sum[i - 1] * nums[i + 1]; } } return result; }
Hence, we reduced the space of O(n). Time and space are not reduced, but we did a small optimization here.
Approach 4: Using Prefix and Suffix product knowledge ?
Intuition
This is a rather easy approach when we use the knowledge of prefix and suffix arrays.
For every given index i, we will calculate the product of all the numbers to the left and then multiply it by the product of all the numbers to the right. This will give us the product of all the numbers except the one at the given index i. Let's look at a formal algorithm that describes this idea more clearly.
Algorithm steps
- Create an array result of the same length as nums to store the final results.
- Create two additional arrays prefix_sum and suffix_sum of the same length as nums.
- Calculate Prefix Products:
- Set the first element of prefix_sum to 1.
- Iterate through the input array nums starting from the second element (index 1). For each index i, set prefix_sum[i] to the product of prefix_sum[i - 1] and nums[i - 1].
- Calculate Suffix Products:
- Set the last element of suffix_sum to 1.
- Iterate through the input array nums starting from the second-to-last element (index nums.length - 2) to the first element.
- For each index i, set suffix_sum[i] to the product of suffix_sum[i + 1] and nums[i + 1].
- Iterate through the input array nums.
- For each index i, set result[i] to the product of prefix_sum[i] and suffix_sum[i].
- Return the result array containing the product of all elements except the current element for each index.
Pseudocode
Function prefixSuffix1(nums): N = length of nums result = new array of length N prefix_sum = new array of length N suffix_sum = new array of length N // Calculate prefix products prefix_sum[0] = 1 For i from 1 to N-1: prefix_sum[i] = prefix_sum[i-1] * nums[i-1] // Calculate suffix products suffix_sum[N-1] = 1 For i from N-2 to 0: suffix_sum[i] = suffix_sum[i+1] * nums[i+1] // Calculate result array For i from 0 to N-1: result[i] = prefix_sum[i] * suffix_sum[i] Return result
Code
private static int[] prefixSuffixProducts(int[] nums) { int[] result = new int[nums.length]; int[] prefix_sum = new int[nums.length]; int[] suffix_sum = new int[nums.length]; prefix_sum[0] = 1; for (int i = 1; i < nums.length; i++) { prefix_sum[i] = prefix_sum[i - 1] * nums[i - 1]; } suffix_sum[nums.length - 1] = 1; for (int i = nums.length - 2; i >= 0; i--) { suffix_sum[i] = suffix_sum[i + 1] * nums[i + 1]; } for (int i = 0; i < nums.length; i++) { result[i] = prefix_sum[i] * suffix_sum[i]; } return result; }
Complexity analysis
-
Time complexity: The time complexity of the given code is O(n), where n is the length of the input array nums. This is because:
- Calculating the prefix_sum products take O(n) time.
- Calculating the suffix_sum products take O(n) time.
- Constructing the result array takes O(n) time.
Each of these steps involves a single pass through the array, resulting in a total time complexity of O(n)+O(n)+O(n) = 3O(n), which is O(n).
-
Space complexity: The space complexity of the given code is O(n). This is because:
- The prefix_sum array requires O(n) space.
- The suffix_sum array requires O(n) space.
- The result array requires O(n) space.
All three arrays are of length n, so the total space complexity is O(n) + O(n) + O(n) = 3O(n), which is O(n).
Approach 5: Carry Forward technique
Intuition
The carry forward technique optimizes us to solve the problem with a more efficient space complexity. Instead of using two separate arrays for prefix and suffix products, we can use the result array itself to store intermediate results and use a single pass for each direction.
Here’s how you can implement the solution using the carry-forward technique:
Algorithm Steps for Carry Forward Technique
- Initialize Result Array:
- Create an array result of the same length as nums to store the final results.
- Calculate Prefix Products:
- Initialize a variable prefixProduct to 1.
- Iterate through the input array nums from left to right. For each index i, set result[i] to the value of prefixProduct. Update prefixProduct by multiplying it with nums[i].
- Calculate Suffix Products and Final Result:
- Initialize a variable suffixProduct to 1.
- Iterate through the input array nums from right to left. For each index i, update result[i] by multiplying it with suffixProduct. Update suffixProduct by multiplying it with nums[i].
- Return the result array containing the product of all elements except the current element for each index.
Pseudocode
prefix products prefixProduct = 1 For i from 0 to N-1: result[i] = prefixProduct prefixProduct = prefixProduct * nums[i] // Calculate suffix products and finalize result suffixProduct = 1 For i from N-1 to 0: result[i] = result[i] * suffixProduct suffixProduct = suffixProduct * nums[i] Return result
Code
// carry forward technique private static int[] carryForward(int[] nums) { int n = nums.length; int[] result = new int[n]; // Calculate prefix products int prefixProduct = 1; for (int i = 0; i < n; i++) { result[i] = prefixProduct; prefixProduct *= nums[i]; } // Calculate suffix products and finalize the result int suffixProduct = 1; for (int i = n - 1; i >= 0; i--) { result[i] *= suffixProduct; suffixProduct *= nums[i]; } return result; }
Explanation
- Prefix Products Calculation:
- We initialize prefixProduct to 1 and update each element of result with the current value of prefixProduct.
- Update prefixProduct by multiplying it with nums[i].
- Suffix Products Calculation:
- We initialize suffixProduct to 1 and update each element of result(which already contains the prefix product) by multiplying it with suffixProduct.
- Update suffixProduct by multiplying it with nums[i].
Complexity analysis
- Time Complexity: O(n) time
- Space Complexity: O(n) (for the result array)
This approach uses only a single extra array (result) and two variables (prefixProduct and suffixProduct), achieving efficient space utilization while maintaining O(n) time complexity.
Atas ialah kandungan terperinci Leetcode : Produk Tatasusunan Kecuali Diri. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas











Penyelesaian masalah dan penyelesaian kepada perisian keselamatan syarikat yang menyebabkan beberapa aplikasi tidak berfungsi dengan baik. Banyak syarikat akan menggunakan perisian keselamatan untuk memastikan keselamatan rangkaian dalaman. …

Penyelesaian untuk menukar nama kepada nombor untuk melaksanakan penyortiran dalam banyak senario aplikasi, pengguna mungkin perlu menyusun kumpulan, terutama dalam satu ...

Pemprosesan pemetaan medan dalam dok sistem sering menemui masalah yang sukar ketika melaksanakan sistem dok: bagaimana untuk memetakan medan antara muka sistem dengan berkesan ...

Mula musim bunga menggunakan versi IntelliJideaultimate ...

Penukaran objek dan tatasusunan Java: Perbincangan mendalam tentang risiko dan kaedah penukaran jenis cast yang betul Banyak pemula Java akan menemui penukaran objek ke dalam array ...

Apabila menggunakan Mybatis-Plus atau Rangka Kerja ORM yang lain untuk operasi pangkalan data, sering diperlukan untuk membina syarat pertanyaan berdasarkan nama atribut kelas entiti. Sekiranya anda secara manual setiap kali ...

Bagaimanakah penyelesaian caching Redis menyedari keperluan senarai kedudukan produk? Semasa proses pembangunan, kita sering perlu menangani keperluan kedudukan, seperti memaparkan ...

Penjelasan terperinci mengenai reka bentuk jadual SKU dan SPU di platform e-dagang Artikel ini akan membincangkan isu reka bentuk pangkalan data SKU dan SPU dalam platform e-dagang, terutamanya bagaimana menangani jualan yang ditentukan pengguna ...
