Diberi matriks NxN dengan 0s dan 1s. Atur setiap baris yang berisi a 0
untuk semua 0
dan atur setiap kolom yang berisi a 0
untuk semua 0
.
Sebagai contoh
1 0 1 1 0
0 1 1 1 0
1 1 1 1 1
1 0 1 1 1
1 1 1 1 1
hasil dalam
0 0 0 0 0
0 0 0 0 0
0 0 1 1 0
0 0 0 0 0
0 0 1 1 0
Seorang Insinyur Microsoft mengatakan kepada saya bahwa ada solusi yang tidak melibatkan memori tambahan, hanya dua variabel boolean dan satu pass, jadi saya mencari jawaban itu.
BTW, bayangkan itu adalah matriks bit, oleh karena itu hanya 1s dan 0s yang diizinkan berada dalam matriks.
algorithm
optimization
puzzle
akun lama-jaircazarin
sumber
sumber
Jawaban:
Ok, jadi saya lelah karena ini jam 3 pagi di sini, tapi saya punya percobaan pertama dengan tepat 2 melewati setiap angka dalam matriks, jadi di O (NxN) dan linear dalam ukuran matriks.
Saya menggunakan kolom pertama dan baris pertama sebagai penanda untuk mengetahui di mana baris / cols hanya dengan 1's. Lalu, ada 2 variabel l dan c yang perlu diingat jika baris / kolom pertama adalah semua 1 juga. Jadi pass pertama mengatur marker dan me-reset sisanya ke 0's.
Lewat kedua menetapkan 1 di tempat baris dan col mana ditandai 1, dan me-reset baris 1 / col tergantung pada l dan c.
Saya sangat ragu bahwa saya dapat dilakukan dalam 1 pass karena kotak pada awalnya tergantung pada kotak pada akhirnya. Mungkin pass kedua saya dapat dibuat lebih efisien ...
sumber
Ini tidak dapat dilakukan dalam satu pass karena bit tunggal memiliki efek pada bit sebelum dan sesudahnya dalam pemesanan apa pun. TKI Apa pun perintah yang Anda lewati array, Anda mungkin akan menemukan 0 yang berarti Anda harus kembali dan mengubah 1 sebelumnya ke 0.
Memperbarui
Orang-orang tampaknya berpikir bahwa dengan membatasi N pada nilai tetap (katakanlah 8) Anda dapat menyelesaikan ini dengan satu pass. Ya itu a) melewatkan poin dan b) bukan pertanyaan awal. Saya tidak akan memposting pertanyaan tentang pengurutan dan mengharapkan jawaban yang dimulai "dengan asumsi Anda hanya ingin mengurutkan 8 hal ...".
Yang mengatakan, itu adalah pendekatan yang masuk akal jika Anda tahu bahwa N sebenarnya terbatas pada 8. Jawaban saya di atas menjawab pertanyaan awal yang tidak memiliki batasan seperti itu.
sumber
Jadi ide saya adalah menggunakan nilai-nilai di baris / kolom terakhir sebagai bendera untuk menunjukkan apakah semua nilai di kolom / baris yang sesuai adalah 1s.
Menggunakan pemindaian Zig Zag melalui seluruh matriks KECUALI baris / kolom terakhir. Di setiap elemen, Anda menetapkan nilai di baris / kolom terakhir ke logika AND dari dirinya sendiri dengan nilai di elemen saat ini. Dengan kata lain, jika Anda menekan 0, baris / kolom terakhir akan diatur ke 0. Jika Anda menjadi 1, nilai di baris / kolom terakhir akan menjadi 1 hanya jika sudah 1. Bagaimanapun mengatur elemen saat ini ke 0.
Setelah selesai, baris / kolom akhir Anda harus memiliki 1s jika kolom / baris terkait diisi dengan 1s.
Lakukan pemindaian linear melalui baris dan kolom terakhir dan cari 1s. Tetapkan 1s dalam elemen yang sesuai dalam tubuh matriks di mana baris terakhir dan kolom keduanya 1s.
Pengkodean akan sulit untuk menghindari kesalahan satu per satu dll, tetapi itu harus bekerja dalam satu pass.
sumber
Saya punya solusi di sini, ini berjalan dalam sekali jalan, dan melakukan semua pemrosesan "di tempat" tanpa memori tambahan (simpan untuk menumbuhkan tumpukan).
Ini menggunakan rekursi untuk menunda penulisan nol yang tentu saja akan menghancurkan matriks untuk baris dan cols lainnya:
sumber
Saya tidak berpikir itu bisa dilakukan. Saat Anda berada di kotak pertama dan nilainya 1, Anda tidak memiliki cara untuk mengetahui apa nilai kotak lainnya di baris dan kolom yang sama. Jadi, Anda harus memeriksa dan jika ada nol, kembali ke kuadrat pertama dan ubah nilainya menjadi nol. Saya akan merekomendasikan melakukannya dalam dua lintasan - lintasan pertama mengumpulkan informasi tentang baris dan kolom mana yang harus di-nolkan (informasi disimpan dalam sebuah array, jadi kami menggunakan memori tambahan). Lewat kedua mengubah nilai. Saya tahu itu bukan solusi yang Anda cari, tetapi saya pikir itu solusi yang praktis. Batasan yang diberikan oleh Anda membuat masalah tidak dapat dipecahkan.
sumber
Saya bisa melakukannya dengan dua variabel integer dan dua lintasan (hingga 32 baris dan kolom ...)
sumber
~
membalikkan semua bit dalam suatu variabel. 0x00000000 menjadi 0x00000000. Saya pada dasarnya memulai dengan semua yang ada, dan menghapus bit untuk baris / kolom ketika saya menemukan 0. CompleteCols memiliki bit 2 dan 3 set, dan CompleteRows memiliki bit 2 dan 4 set (0 based).masalahnya bisa diselesaikan dalam satu pass
menyimpan matriks dalam array i X j.
sekarang cetak semua nilai sebagai 0 untuk nilai i dan j yang disimpan dalam a dan b sisanya dari nilai tersebut yaitu 1 yaitu (3,3) (3,4) (5,3) dan (5,4)
sumber
Solusi lain yang membutuhkan dua lintasan, adalah mengakumulasi AND secara horizontal dan vertikal:
Saya pikir saya bisa merancang algoritma seperti itu menggunakan bit paritas , kode Hamming atau pemrograman dinamis , mungkin menggunakan dua boolean sebagai angka 2-bit, tapi saya belum berhasil.
Bisakah Anda memeriksa kembali pernyataan masalah dengan insinyur Anda dan beri tahu kami? Jika ada yang memang solusi, aku ingin terus chipping jauh di masalah.
sumber
Simpan satu variabel untuk melacak semua baris ANDed bersama.
Jika satu baris adalah -1 (semua 1s), maka buat baris berikutnya sebagai referensi ke variabel itu
Jika satu baris adalah sesuatu tetapi, itu adalah 0. Anda dapat melakukan semuanya dalam satu pass. Kode psuedo:
Itu harus melakukannya, dalam sekali lulus - tetapi ada asumsi di sini bahwa N cukup kecil untuk CPU untuk melakukan aritmatika pada satu baris, jika tidak, Anda akan perlu untuk mengulang setiap baris untuk menentukan apakah itu semua 1s atau tidak, saya percaya. Tetapi mengingat Anda bertanya tentang algos dan tidak membatasi perangkat keras saya, saya hanya akan memulai jawaban saya dengan "Bangun CPU yang mendukung aritmatika N-bit ..."
Inilah salah satu contoh bagaimana hal itu dapat dilakukan dalam C. Catatan saya berpendapat bahwa nilai dan arr yang diambil bersama-sama mewakili array, dan p dan numproduct adalah iterator saya dan variabel produk AND digunakan untuk mengimplementasikan masalah. (Saya bisa mengulangi arr dengan pointer aritmatika untuk memvalidasi pekerjaan saya, tetapi sekali sudah cukup!)
Ini menghasilkan 0, 0, 6, 0, 6, yang merupakan hasil untuk input yang diberikan.
Atau di PHP, jika orang berpikir bahwa permainan tumpukan saya di C curang (saya sarankan Anda tidak melakukannya, karena saya harus dapat menyimpan matriks mana pun yang saya inginkan):
Apakah saya melewatkan sesuatu?
sumber
Tantangan yang bagus. Solusi ini menggunakan hanya dua boolean yang dibuat di stack, tetapi boolean dibuat beberapa kali di stack karena fungsinya bersifat rekursif.
Ini memindai dalam pola seperti:
dan seterusnya
Dan kemudian mengubah nilai-nilai dalam pola ini setelah kembali pada masing-masing fungsi pemindaian. (Bawah ke atas):
dan seterusnya
sumber
Oke ini solusinya
sumber
Sebenarnya. Jika Anda hanya ingin menjalankan algoritme dan mencetak hasilnya (yaitu tidak mengembalikannya, maka ini dapat dengan mudah dilakukan dalam satu langkah. Masalahnya muncul ketika Anda mencoba memodifikasi array saat Anda menjalankan algoritma.
Inilah solusi saya. Ini hanya melibatkan ANDing nilai baris / kolom untuk elemen givein (i, j) dan mencetaknya.
sumber
Saya mencoba menyelesaikan masalah ini dalam C #.
Saya telah menggunakan dua variabel loop (i dan j) selain dari matriks aktual dan n yang mewakili dimensinya
Logika yang saya coba adalah:
Kode:
sumber
One Pass - Saya telah melewati input hanya sekali tetapi menggunakan array baru dan hanya dua variabel Boolean tambahan.
sumber
Meskipun tidak mungkin mengingat kendala, cara paling efisien ruang untuk melakukannya adalah dengan melintasi matriks dengan cara baris / kolom bergantian yang tumpang tindih, yang akan membuat pola yang mirip dengan meletakkan batu bata dalam mode zig-zag:
Dengan menggunakan ini, Anda akan pergi di setiap baris / kolom, seperti yang ditunjukkan, dan jika Anda menemukan 0 setiap saat, atur variabel boolean, dan berjalan kembali baris / kolom itu, atur entri ke 0 saat Anda pergi.
Ini tidak memerlukan memori tambahan, dan hanya akan menggunakan satu variabel boolean. Sayangnya, jika tepi "jauh" diatur ke semua menjadi 0, itu adalah kasus terburuk dan Anda berjalan di seluruh array dua kali.
sumber
buat matriks hasil dan atur semua nilai ke 1. pergi melalui matriks data segera setelah 0 ditemui, atur kolom baris matriks hasil ke 0
Pada akhir pass pertama, matriks hasil akan memiliki jawaban yang benar.
Terlihat sangat sederhana. Apakah ada trik yang saya lewatkan? Apakah Anda tidak diizinkan menggunakan set hasil?
EDIT:
Tampak seperti fungsi F #, tetapi itu sedikit curang karena meskipun Anda melakukan satu lintasan, fungsi tersebut dapat bersifat rekursif.
Sepertinya pewawancara sedang mencoba mencari tahu apakah Anda tahu pemrograman fungsional.
sumber
Yah, saya datang dengan solusi single-pass, in-place (non-rekursif) menggunakan 4 bools dan 2 loop counter. Saya belum berhasil menguranginya menjadi 2 bools dan 2 int, tapi saya tidak akan terkejut jika itu mungkin. Itu sekitar 3 membaca dan 3 menulis dari setiap sel, dan itu harus O (N ^ 2) yaitu. linear dalam ukuran array.
Butuh waktu beberapa jam untuk memecahkan teka-teki ini - saya tidak mau harus membuatnya di bawah tekanan wawancara! Jika saya membuat booboo saya terlalu lelah untuk menemukannya ...
Um ... Saya memilih untuk mendefinisikan "single-pass" sebagai membuat satu sapuan melalui matriks, daripada menyentuh setiap nilai sekali! :-)
sumber
saya harap Anda menikmati solusi 1-pass c # saya
Anda dapat mengambil elemen dengan O (1) dan hanya membutuhkan ruang satu baris dan satu kolom dari matriks
sumber
1 lulus, 2 boolean. Saya hanya harus mengasumsikan indeks integer di iterasi tidak masuk hitungan.
Ini bukan solusi lengkap tapi saya tidak bisa melewati titik ini.
Jika saya hanya bisa menentukan apakah 0 adalah asli 0 atau 1 yang dikonversi menjadi 0 maka saya tidak perlu menggunakan -1 dan ini akan berhasil.
Output saya seperti ini:
Orisinalitas pendekatan saya menggunakan paruh pertama pemeriksaan baris atau kolom untuk menentukan apakah mengandung 0 dan setengah terakhir untuk menetapkan nilai - ini dilakukan dengan melihat x dan lebar-x dan kemudian y dan tinggi -Y di setiap iterasi. Berdasarkan hasil paruh pertama iterasi, jika 0 di baris atau kolom ditemukan, saya menggunakan paruh terakhir iterasi untuk mengubah 1 ke -1.
Saya baru menyadari ini bisa dilakukan dengan hanya 1 boolean menyisakan 1 untuk ...?
Saya memposting ini berharap seseorang mungkin berkata, "Ah, lakukan saja ini ..." (Dan saya menghabiskan terlalu banyak waktu untuk tidak memposting.)
Berikut kode di VB:
sumber
Tidak ada yang menggunakan bentuk biner? karena hanya 1 dan 0. Kita bisa menggunakan vektor biner.
Inilah tesnya:
Dan hasilnya:
sumber
Anda dapat melakukan sesuatu seperti ini untuk menggunakan satu pass tetapi input dan output matrix:
di mana
col(xy)
bit dalam kolom berisi titikxy
;row(xy)
adalah bit di baris yang mengandung titikxy
.n
adalah ukuran dari matriks.Kemudian cukup lewati input. Mungkin dapat diperluas agar lebih hemat ruang?
sumber
Satu pemindaian matriks, dua boolean, tanpa rekursi.
Bagaimana cara menghindari lulus kedua? Pass kedua diperlukan untuk menghapus baris atau kolom ketika nol muncul di akhir mereka.
Namun masalah ini dapat diselesaikan, karena ketika kita memindai baris # i kita sudah tahu status baris untuk baris # i-1. Jadi, ketika kita memindai baris # i, kita dapat menghapus baris # i-1 secara bersamaan jika diperlukan.
Solusi yang sama berfungsi untuk kolom, tetapi kita perlu memindai baris dan kolom secara bersamaan sementara data tidak diubah oleh iterasi berikutnya.
Diperlukan dua boolean untuk menyimpan status baris pertama dan kolom pertama, karena nilainya akan berubah selama eksekusi bagian utama dari algoritma.
Untuk menghindari menambahkan lebih banyak boolean, kami menyimpan flag "clear" untuk baris dan kolom di baris dan kolom pertama dari matriks.
sumber
Sepertinya karya-karya berikut tanpa persyaratan ruang tambahan:
pertama-tama perhatikan bahwa mengalikan elemen-elemen dari baris kali dengan elemen-elemen dari baris di mana sebuah elemen, memberikan nilai yang diinginkan.
Agar tidak menggunakan ruang tambahan apa pun (tidak membuat matriks baru dan mengisinya, tetapi langsung menerapkan perubahan pada matriks), mulailah dari kiri atas matriks dan lakukan perhitungan untuk matriks ixi apa pun (yang "dimulai" pada (0) , 0)) sebelum mempertimbangkan elemen apa pun dengan indeks apa pun> i.
Semoga ini berhasil (havent testet)
sumber
Ini DIUJI untuk N berbeda dalam C ++, dan adalah:
SATU LULUS , DUA BULU , TANPA PEREKAMAN , TANPA MEMORI EKSTRA , TERLENGKAPNYA UNTUK BESARNYA SECARA ARBITRAR
(Sejauh ini tidak ada solusi di sini yang melakukan SEMUA ini.)
Lebih khusus, saya lucu dua loop counter tidak apa-apa. Saya memiliki dua const unsigned, yang hanya ada daripada dihitung setiap kali untuk dibaca. Interval loop luar adalah [0, N], dan interval loop dalam adalah [1, n - 1]. Pernyataan switch dalam loop sebagian besar ada untuk menunjukkan dengan sangat jelas bahwa itu hanya satu pass.
Strategi Algoritma:
Trik pertama adalah bagi kita satu baris dan kolom dari matriks itu sendiri untuk mengakumulasi konten matriks, memori ini menjadi tersedia dengan melepas semua yang benar-benar perlu kita ketahui dari baris pertama dan kolom menjadi dua boolean. Trik kedua adalah untuk mendapatkan dua pass dari satu, dengan menggunakan simetri dari sub-matriks dan indeksnya.
Sinopsis Algoritma:
Implementasi Templatized C ++:
sumber
Ok, saya menyadari bahwa itu tidak cocok, tapi saya mendapatkannya dalam satu pass menggunakan bool dan byte alih-alih dua bools ... tutup. Saya juga tidak akan menjamin efisiensi, tetapi jenis pertanyaan ini sering membutuhkan solusi yang kurang optimal.
sumber
Anda dapat mengurutkannya dalam satu pass - jika Anda tidak menghitung mengakses matriks dalam urutan akses acak, yang menghilangkan manfaat melakukannya dengan single-pass di tempat pertama (cache-coherence / memory-bandwidth).
[edit: solusi sederhana, tetapi salah dihapus]
Anda harus mendapatkan kinerja yang lebih baik daripada metode single-pass dengan melakukannya dalam dua lintasan: satu untuk mengumpulkan informasi baris / kolom, dan satu untuk menerapkannya. Array (dalam urutan baris-utama) diakses secara koheren; untuk array yang melebihi ukuran cache (tetapi baris yang dapat ditampung dalam cache), data harus dibaca dari memori dua kali, dan disimpan satu kali:
sumber
Solusi paling sederhana yang dapat saya pikirkan adalah ditempelkan di bawah ini. Logikanya adalah untuk merekam baris dan kolom mana yang akan disetel nol saat iterasi.
sumber
Berikut ini adalah implementasi Ruby saya dengan tes yang disertakan, Ini akan mengambil ruang O (MN). Jika kita menginginkan pembaruan waktu nyata (ingin menunjukkan hasil ketika kita menemukan nol daripada menunggu loop pertama untuk menemukan nol) kita bisa membuat variabel kelas lain seperti
@output
dan setiap kali kita menemukan nol kita memperbarui@output
dan tidak@input
.sumber
Kode di bawah ini membuat matriks ukuran m, n. Pertama-tama tentukan dimensi matriks. Saya ingin mengisi matriks [m] [n] dengan secara acak dengan angka antara 0..10. Kemudian buat matriks lain dari dimensi yang sama dan isi dengan -1s (final matrix). Kemudian beralih melalui matriks awal untuk melihat apakah Anda akan menekan 0. Ketika Anda menekan pada lokasi (x, y), pergi ke matriks akhir dan isi baris x dengan 0s dan kolom y dengan 0s. Pada akhir membaca matriks akhir, jika nilainya -1 (nilai asli) salin nilai di lokasi yang sama dari matriks awal ke final.
sumber
ini solusinya. Seperti yang dapat Anda lihat dari kode, diberikan matriks M * N, ia menetapkan seluruh baris menjadi nol setelah memeriksa nol di baris itu. Kompleksitas waktu dari solusi saya adalah O (M * N). Saya berbagi seluruh kelas yang memiliki larik statis yang dihuni untuk pengujian dan metode larik tampilan untuk melihat hasilnya di konsol.
}
sumber