Đặt mọi ô trong ma trận thành 0 nếu hàng hoặc cột đó chứa 0


152

Cho ma trận NxN có 0 và 1. Đặt mọi hàng có chứa a 0cho tất cả 0s và đặt mỗi cột chứa a 0cho tất cả 0s.

Ví dụ

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

kết quả trong

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

Một kỹ sư của Microsoft nói với tôi rằng có một giải pháp không cần thêm bộ nhớ, chỉ có hai biến boolean và một biến, vì vậy tôi đang tìm câu trả lời đó.

BTW, hãy tưởng tượng nó là một ma trận bit, do đó chỉ cần 1s và 0 được cho phép trong ma trận.


1
Huh? "Bất cứ khi nào bạn gặp phải" là gì? Theo thứ tự bạn đang gặp các yếu tố trong ma trận? Và nếu bạn gặp phải tất cả các bit, bạn sẽ không nhận được tất cả 0 chứ?
ShreevatsaR

Chà, thứ tự mà bạn quyết định gặp các yếu tố là quyết định của bạn, điều là bạn chỉ phải đặt thành 0s các yếu tố thích hợp. Nếu bạn gặp tất cả các bit được đặt thành 0, có, ma trận sẽ vẫn được điền bằng 0.
jaircazarin-tài khoản cũ

"Các yếu tố thích hợp" là gì? Bạn có được cung cấp hai ma trận, một ma trận "nguồn" và một ma trận "đích" và bạn phải quyết định theo thứ tự nào để "gặp" các yếu tố để có được ma trận "đích"?
ShreevatsaR

1
Tôi nghĩ rằng bạn nghe nhầm một cái gì đó cho suy nghĩ '1 vượt qua'. Nó có thể được thực hiện tuyến tính trong 2 lần, mặc dù không có bộ nhớ thêm, chỉ có 2 booleans ;-) Vì vậy, tôi mạnh mẽ cho rằng đó là giải pháp mà anh ấy muốn nói (xem bên dưới)
Piotr Lesnicki

1
Bạn có thể vui lòng kiểm tra lại với bạn bè của bạn nếu mô tả vấn đề thực sự chính xác? Tôi nghĩ rằng tôi có thể làm điều này với mã Hamming hoặc bit chẵn lẻ, nhưng cho đến nay tôi đã không thành công và vấn đề cứ liên tục xuất hiện trong đầu tôi. :)
csl

Câu trả lời:


96

Ok, vì vậy tôi mệt mỏi vì đây là 3 giờ sáng, nhưng tôi đã thử lần đầu tiên với đúng 2 lần truyền cho mỗi số trong ma trận, vì vậy trong O (NxN) và nó có kích thước tuyến tính theo ma trận.

Tôi sử dụng cột 1rst và hàng đầu tiên làm điểm đánh dấu để biết các hàng / cols chỉ có 1 giây ở đâu. Sau đó, có 2 biến l và c cần nhớ nếu hàng 1 cột / cột cũng đều là 1. Vì vậy, đường chuyền đầu tiên đặt các điểm đánh dấu và đặt lại phần còn lại thành 0.

Pass thứ hai đặt 1 ở những nơi hàng và cols được đánh dấu là 1 và đặt lại dòng 1 / col tùy thuộc vào l và c.

Tôi nghi ngờ mạnh mẽ rằng tôi có thể được thực hiện trong 1 lượt như hình vuông lúc đầu phụ thuộc vào hình vuông cuối cùng. Có lẽ đường chuyền thứ 2 của tôi có thể được thực hiện hiệu quả hơn ...

import pprint

m = [[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]]



N = len(m)

### pass 1

# 1 rst line/column
c = 1
for i in range(N):
    c &= m[i][0]

l = 1
for i in range(1,N):
    l &= m[0][i]


# other line/cols
# use line1, col1 to keep only those with 1
for i in range(1,N):
    for j in range(1,N):
        if m[i][j] == 0:
            m[0][j] = 0
            m[i][0] = 0
        else:
            m[i][j] = 0

### pass 2

# if line1 and col1 are ones: it is 1
for i in range(1,N):
    for j in range(1,N):
        if m[i][0] & m[0][j]:
            m[i][j] = 1

# 1rst row and col: reset if 0
if l == 0:
    for i in range(N):
        m [i][0] = 0

if c == 0:
    for j in range(1,N):
        m [0][j] = 0


pprint.pprint(m)

Một vấn đề ở đây là nếu n> sizeof (c) thì nó bị hỏng. Để mở rộng điều này để hoạt động trong trường hợp chung của n, bạn sẽ cần phải tự động kích thước trường bit của mình mà tôi nghĩ sẽ vi phạm các ràng buộc do vấn đề đưa ra.
Adam

Không, c không phải là một bitfield, nó chỉ là một bool. & = Không phải là bit bit (tốt, đúng vậy, nhưng trên giá trị 1 bit), nó ở đó bởi vì c cho bạn biết cột đầu tiên là tất cả 1 (đúng) hay chứa 0 (sai).
Steve Jessop

2
Không thành công nếu hàng trên cùng là [0,1,1,1 ...] Sửa lỗi của tôi là khởi tạo l thành m [0] [0] chứ không phải 1
paperhorse

thực sự l = 1 cho i trong phạm vi (1, N): l & = m [0] [i] nên l = 1 cho i trong phạm vi (N): l & = m [0] [i]
Kristof Neirynck

1
BTW, tôi tin rằng điều kiện trong lần chuyển thứ hai phải giống như: if m [i] [0] | m [0] [j]:
jaircazarin-tài khoản cũ

16

Điều này không thể được thực hiện trong một lần vì một bit có ảnh hưởng đến các bit trước và sau nó theo bất kỳ thứ tự nào. IOW Bất kể thứ tự nào bạn đi qua mảng, sau đó bạn có thể đi qua 0 có nghĩa là bạn phải quay lại và thay đổi 1 trước đó thành 0.

Cập nhật

Mọi người dường như nghĩ rằng bằng cách giới hạn N ở một số giá trị cố định (giả sử 8), bạn có thể giải quyết đây là một lần vượt qua. Vâng, đó là a) thiếu điểm và b) không phải là câu hỏi ban đầu. Tôi sẽ không đăng câu hỏi về sắp xếp và mong đợi một câu trả lời bắt đầu "giả sử bạn chỉ muốn sắp xếp 8 điều ...".

Điều đó nói rằng, đó là một cách tiếp cận hợp lý nếu bạn biết rằng N thực tế bị giới hạn ở 8. Câu trả lời của tôi ở trên trả lời câu hỏi ban đầu không có câu trả lời như vậy.


Nó không thể được thực hiện trong một lần mà không có bộ nhớ bổ sung. Nó có thể được thực hiện trong một lần nếu có một ma trận NxN khác để lưu trữ kết quả. Tương tự như vậy, với một số câu đố nhỏ và hai lần vượt qua nó có thể được thực hiện mà không cần thêm bộ nhớ.
paxos1977

2
Bạn vẫn không thể làm điều đó trong một lần ngay cả khi bạn sử dụng ma trận tạm thời, nếu không thì có điều gì đó kỳ lạ tôi không đến đây. Bạn cần một lượt để suy ra thông tin hàng / cột và một để đặt mọi thứ.
Lasse V. Karlsen

Tôi đã giải quyết vấn đề này bằng cách nhận ra rằng chỉ có một giá trị duy nhất khác không có thể có trên mỗi hàng và chỉ cần gán nó bằng tham chiếu.
Daniel Papasian

@ceretullis, lassevk: Tôi vẫn nghĩ rằng nó không thể được thực hiện trong một lần. Vượt qua ma trận thứ hai đó sẽ phải tính - nếu không bạn chỉ có thể sao chép ma trận trong một lần và làm việc với bản sao theo cách bạn muốn. @Daniel Papasian: Giải pháp của bạn không mở rộng quy mô trong đó N> #bits trong int / long / anything
Draemon

Draemon, kỹ thuật có quy mô tốt, nó chỉ là toán học - bạn có thể xây dựng phần cứng làm điều đó hoặc bạn có thể sử dụng các kỹ thuật phần mềm để thao tác các số lớn hơn kích thước từ của bạn. Không vi phạm các ràng buộc của vấn đề, IMHO
Daniel Papasian

10

Vì vậy, ý tưởng của tôi là sử dụng các giá trị trong hàng / cột cuối cùng làm cờ để cho biết liệu tất cả các giá trị trong cột / hàng tương ứng có phải là 1s hay không.

Sử dụng quét Zig Zag trong toàn bộ ma trận NGOẠI TRỪ hàng / cột cuối cùng. Tại mỗi phần tử, bạn đặt giá trị trong hàng / cột cuối cùng thành logic AND của chính nó với giá trị trong phần tử hiện tại. Nói cách khác, nếu bạn nhấn 0, hàng / cột cuối cùng sẽ được đặt thành 0. Nếu bạn là 1, giá trị trong hàng / cột cuối cùng sẽ chỉ là 1 nếu đã là 1. Trong mọi trường hợp, đặt phần tử hiện tại thành 0.

Khi bạn hoàn thành, hàng / cột cuối cùng của bạn sẽ có 1 giây nếu cột / hàng tương ứng được điền 1s.

Thực hiện quét tuyến tính qua hàng và cột cuối cùng và tìm kiếm 1 giây. Đặt 1s trong các phần tử tương ứng trong phần thân của ma trận trong đó hàng và cột cuối cùng đều là 1s.

Mã hóa sẽ rất khó để tránh các lỗi khác nhau, nhưng nó sẽ hoạt động trong một lần.


Rất hay ... Tôi đã suy nghĩ trên cùng một dòng, nhưng đã bỏ lỡ việc sử dụng hàng / cột cuối cùng để lưu trữ thông tin đó, vì vậy tôi bị kẹt với bộ nhớ thêm cho một cặp mảng Nx1.
Dave Sherohman

1
Trông giống như hai lần truyền cho tôi - một lần là quét zig-zag, lần thứ hai là "Đặt 1 trong các phần tử tương ứng trong phần thân của ma trận trong đó hàng và cột cuối cùng đều là 1s".
Adam Rosenfield

Quá trình quét zig-zag (mà như ai đó đã chỉ ra cho tôi không thực sự cần thiết) đi qua tất cả NHƯNG hàng / cột cuối cùng. Vì vậy, quét cột cuối cùng / hàng không trùng lặp các yếu tố được quét trước đó. Do đó một lượt vượt qua. Nói cách khác, đó là O (N ^ 2) cho ma trận N * N.
Alastair

6

Tôi đã có một giải pháp ở đây, nó chạy trong một lần duy nhất và thực hiện tất cả xử lý "tại chỗ" mà không cần thêm bộ nhớ (tiết kiệm để phát triển ngăn xếp).

Nó sử dụng đệ quy để trì hoãn việc viết các số không, điều này tất nhiên sẽ phá hủy ma trận cho các hàng và cols khác:

#include <iostream>

/**
* The idea with my algorithm is to delay the writing of zeros
* till all rows and cols can be processed. I do this using
* recursion:
* 1) Enter Recursive Function:
* 2) Check the row and col of this "corner" for zeros and store the results in bools
* 3) Send recursive function to the next corner
* 4) When the recursive function returns, use the data we stored in step 2
*       to zero the the row and col conditionally
*
* The corners I talk about are just how I ensure I hit all the row's a cols,
* I progress through the matrix from (0,0) to (1,1) to (2,2) and on to (n,n).
*
* For simplicities sake, I use ints instead of individual bits. But I never store
* anything but 0 or 1 so it's still fair ;)
*/

// ================================
// Using globals just to keep function
// call syntax as straight forward as possible
int n = 5;
int m[5][5] = {
                { 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 }
            };
// ================================

// Just declaring the function prototypes
void processMatrix();
void processCorner( int cornerIndex );
bool checkRow( int rowIndex );
bool checkCol( int colIndex );
void zeroRow( int rowIndex );
void zeroCol( int colIndex );
void printMatrix();

// This function primes the pump
void processMatrix() {
    processCorner( 0 );
}

// Step 1) This is the heart of my recursive algorithm
void processCorner( int cornerIndex ) {
    // Step 2) Do the logic processing here and store the results
    bool rowZero = checkRow( cornerIndex );
    bool colZero = checkCol( cornerIndex );

    // Step 3) Now progress through the matrix
    int nextCorner = cornerIndex + 1;
    if( nextCorner < n )
        processCorner( nextCorner );

    // Step 4) Finially apply the changes determined earlier
    if( colZero )
        zeroCol( cornerIndex );
    if( rowZero )
        zeroRow( cornerIndex );
}

// This function returns whether or not the row contains a zero
bool checkRow( int rowIndex ) {
    bool zero = false;
    for( int i=0; i<n && !zero; ++i ) {
        if( m[ rowIndex ][ i ] == 0 )
            zero = true;
    }
    return zero;
}

// This is just a helper function for zeroing a row
void zeroRow( int rowIndex ) {
    for( int i=0; i<n; ++i ) {
        m[ rowIndex ][ i ] = 0;
    }
}

// This function returns whether or not the col contains a zero
bool checkCol( int colIndex ) {
    bool zero = false;
    for( int i=0; i<n && !zero; ++i ) {
        if( m[ i ][ colIndex ] == 0 )
            zero = true;
    }

    return zero;
}

// This is just a helper function for zeroing a col
void zeroCol( int colIndex ) {
    for( int i=0; i<n; ++i ) {
        m[ i ][ colIndex ] = 0;
    }
}

// Just a helper function for printing our matrix to std::out
void printMatrix() {
    std::cout << std::endl;
    for( int y=0; y<n; ++y ) {
        for( int x=0; x<n; ++x ) {
            std::cout << m[y][x] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

// Execute!
int main() {
    printMatrix();
    processMatrix();
    printMatrix();
}

2
Giải pháp tốt, nhưng về mặt kỹ thuật, bạn sử dụng nhiều bộ nhớ hơn hai booleans được phép (mặc dù trên ngăn xếp).
csl

1
Đây là> 1 vượt qua. Nếu bạn in (row Index, i) và (i, col Index) khi chúng được truy cập trong checkRow và checkCol, bạn sẽ thấy rằng mỗi phần tử được truy cập nhiều lần.
Draemon

Draemon: Bạn đã đúng, tôi nghĩ rằng chúng ta cần một định nghĩa rõ ràng về "một lần vượt qua" từ nhà sản xuất câu đố. Nếu anh ta thực sự có nghĩa là mỗi phần tử chỉ có thể được truy cập một lần, thì chúng ta cần một giải pháp khác nhau.
Adam

Tôi tưởng tượng vấn đề ban đầu (đã đến với chúng tôi thông qua trò chơi điện thoại) có nghĩa là vấn đề cần được giải quyết "tại chỗ" nghĩa là bạn không có một bản sao khác của ma trận. Và các giải pháp tối ưu hơn thậm chí không cần trao đổi tạm thời () như lưu trữ để xử lý.
Adam

Ngoài ra, tôi nghi ngờ các ràng buộc đang đề cập đến mã máy kết quả. Có nghĩa là, "mã" tôi cung cấp chỉ sử dụng 2 bools. Tùy thuộc vào những gì tối ưu hóa trình biên dịch của tôi làm, toàn bộ điều ngu ngốc có thể được nội tuyến hoặc ai biết những gì khác. Tôi nghĩ rằng giải pháp của tôi là đúng;)
Adam

4

Tôi không nghĩ rằng nó có thể làm được. Khi bạn ở trên hình vuông đầu tiên và giá trị của nó là 1, bạn không có cách nào để biết giá trị của các hình vuông khác trong cùng một hàng và cột là gì. Vì vậy, bạn phải kiểm tra những cái đó và nếu có số 0, quay lại hình vuông đầu tiên và thay đổi giá trị của nó thành số không. Tôi sẽ khuyên bạn nên thực hiện trong hai lần - lần đầu tiên tập hợp thông tin về các hàng và cột phải được loại bỏ (thông tin được lưu trữ trong một mảng, vì vậy chúng tôi đang sử dụng thêm một số bộ nhớ). Pass thứ hai thay đổi các giá trị. Tôi biết đó không phải là giải pháp bạn đang tìm kiếm, nhưng tôi nghĩ đó là một giải pháp thiết thực. Các ràng buộc do bạn đưa ra khiến vấn đề không thể giải quyết được.


Tôi có gần như cùng một giải pháp (xem bên dưới) mà không cần thêm mảng. và đó là thời gian tuyến tính (nhưng 2 lần trôi qua)
Piotr Lesnicki

@Piotr: Vâng, đường chuyền thứ hai dường như không thể tránh khỏi. Việc giới thiệu các mảng để lưu trữ thông tin hàng và cột mà tôi đã đề xuất làm cho thuật toán trở nên đơn giản hơn và nhanh hơn một chút vì có ít kiểm tra và thay đổi giá trị. Đó là sự đánh đổi giữa lưu trữ và hiệu quả.
Boyan

3

Tôi có thể làm điều đó với hai biến số nguyên và hai lần chuyển (tối đa 32 hàng và cột ...)

bool matrix[5][5] = 
{ 
    {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}
};

int CompleteRows = ~0;
int CompleteCols = ~0;

// Find the first 0
for (int row = 0; row < 5; ++row)
{
    for (int col = 0; col < 5; ++col)
    {
        CompleteRows &= ~(!matrix[row][col] << row);
        CompleteCols &= ~(!matrix[row][col] << col);
    }
}

for (int row = 0; row < 5; ++row)
    for (int col = 0; col < 5; ++col)
        matrix[row][col] = (CompleteRows & (1 << row)) && (CompleteCols & (1 << col));

Đây có phải là C # không? ~ Có nghĩa là gì?
trượt ván

Đó là C ++. ~đảo ngược tất cả các bit trong một biến. 0x00000000 trở thành 0x00000000. Về cơ bản, tôi bắt đầu với tất cả các cái và xóa bit cho một hàng / cột khi tôi tìm thấy 0. CompleteCols có các bit 2 và 3 và CompleteRows có các bit 2 và 4 (dựa trên 0).
Nhật thực

Sau đó, bạn chỉ cần đặt các bit trong ma trận tương ứng với một bit trong cả CompleteCols và CompleteRows.
Nhật thực

3

vấn đề có thể được giải quyết trong một lần

lưu ma trận trong một mảng i X j.

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

one each pass save the values of i and j for an element which is 0 in arrays a and b
when first row is scanned a= 1 b = 2,5
when second row is scanned a=1,2 b= 1,2,5
when third row is scanned no change
when fourth row is scanned a= 1,2,4 and b= 1,2,5
when fifth row is scanned no change .

bây giờ in tất cả các giá trị là 0 cho các giá trị của i và j được lưu trong a và b phần còn lại của các giá trị là 1 tức là (3,3) (3,4) (5,3) và (5,4)


1

Một giải pháp khác cần hai lần, là tích lũy AND theo chiều ngang và chiều dọc:

1 0 1 1 0 | 0
0 1 1 1 0 | 0
1 1 1 1 1 | 1
1 0 1 1 1 | 0
1 1 1 1 1 | 1
----------+
0 0 1 1 0    

Tôi nghĩ rằng tôi có thể thiết kế một thuật toán như vậy bằng cách sử dụng các bit chẵn lẻ , mã Hamming hoặc lập trình động , có thể sử dụng hai booleans đó làm số 2 bit, nhưng tôi chưa thành công.

Bạn có thể vui lòng kiểm tra lại báo cáo vấn đề với kỹ sư của bạn và cho chúng tôi biết? Nếu có thực sự là một giải pháp, tôi muốn giữ lại sứt mẻ đi vào vấn đề.


1

Giữ một biến duy nhất để theo dõi tất cả các hàng ANDed với nhau là gì.

Nếu một hàng là -1 (tất cả 1 giây), thì hãy tạo hàng tiếp theo làm tham chiếu đến biến đó

Nếu một hàng là bất cứ thứ gì, nhưng đó là 0. Bạn có thể làm mọi thứ trong một lần. Mã Psuedo:

foreach (my $row) rows {
     $andproduct = $andproduct & $row;
     if($row != -1) {
        zero out the row
     }  else {
        replace row with a reference to andproduct
     }
}

Điều đó sẽ làm điều đó, trong một lần duy nhất - nhưng có một giả định ở đây là N đủ nhỏ để CPU thực hiện số học trên một hàng, nếu không bạn sẽ phải lặp qua từng hàng để xác định xem có phải là tất cả không 1s hay không, tôi tin. Nhưng khi bạn hỏi về thuật toán và không hạn chế phần cứng của mình, tôi sẽ chỉ bắt đầu câu trả lời của mình với "Xây dựng CPU hỗ trợ số học N-bit ..."

Dưới đây là một ví dụ về cách có thể thực hiện trong C. Lưu ý Tôi cho rằng các giá trị và mảng được kết hợp với nhau đại diện cho mảng và p và numproduct là các biến lặp và sản phẩm AND của tôi sử dụng để thực hiện vấn đề. (Tôi có thể đã lặp qua các mảng với số học con trỏ để xác thực công việc của mình, nhưng một lần là đủ!)

int main() {
    int values[] = { -10, 14, -1, -9, -1 }; /* From the problem spec, converted to decimal for my sanity */
    int *arr[5] = { values, values+1, values+2, values+3, values+4 };
    int **p;
    int numproduct = 127;

    for(p = arr; p < arr+5; ++p) {
        numproduct = numproduct & **p;
        if(**p != -1) {
            **p = 0;
        } else {
            *p = &numproduct;
        }
    }

    /* Print our array, this loop is just for show */
    int i;
    for(i = 0; i < 5; ++i) {
        printf("%x\n",*arr[i]);
    }
    return 0;
}

Điều này tạo ra 0, 0, 6, 0, 6, là kết quả cho các đầu vào đã cho.

Hoặc trong PHP, nếu mọi người nghĩ rằng các trò chơi ngăn xếp của tôi trong C là gian lận (tôi đề nghị với bạn rằng không phải như vậy, vì tôi có thể lưu trữ ma trận theo bất cứ cách nào tôi muốn):

<?php

$values = array(-10, 14, -1, -9, -1);
$numproduct = 127;

for($i = 0; $i < 5; ++$i) {
    $numproduct = $numproduct & $values[$i];
    if($values[$i] != -1) {
        $values[$i] = 0;
    } else {
        $values[$i] = &$numproduct;
    }
}

print_r($values);

Tui bỏ lỡ điều gì vậy?


Điều này không hoạt động nếu N lớn hơn số bit trong một int / long / bất cứ điều gì vì vậy tôi không nghĩ rằng nó được tính.
Draemon

Nó cũng sẽ không bắt được mọi thứ nếu 0 ở dưới cùng của mảng (thử nó với các giá trị [] = {-1, -9, -1, 14, -10}).
Nhật thực

Draemon, tôi xác định trong câu trả lời của mình rằng không có ràng buộc về phần cứng như một phần của câu hỏi, bạn bắt đầu với "Xây dựng CPU hỗ trợ số học N-bit".
Daniel Papasian

Josh, tôi không theo dõi. Với giải pháp C hoặc PHP và mảng bạn đề xuất, tôi nhận được 6 0 6 0 0, mà tôi tin là câu trả lời đúng.
Daniel Papasian

@Daniel - Bạn không thể, bởi vì N không phải là hằng số. Bên cạnh đó "xây dựng một máy tính mới với các từ 1Mbit hầu như không phải là một bước thuật toán hợp lý.
Draemon

1

Challange đẹp. Giải pháp này sử dụng chỉ hai booleans được tạo trên stack, nhưng booleans được tạo nhiều lần trên stack vì hàm này được đệ quy.

typedef unsigned short     WORD;
typedef unsigned char      BOOL;
#define true  1
#define false 0
BYTE buffer[5][5] = {
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
};
int scan_to_end(BOOL *h,BOOL *w,WORD N,WORD pos_N)
{
    WORD i;
    for(i=0;i<N;i++)
    {
        if(!buffer[i][pos_N])
            *h=false;
        if(!buffer[pos_N][i])
            *w=false;
    }
    return 0;
}
int set_line(BOOL h,BOOL w,WORD N,WORD pos_N)
{
    WORD i;
    if(!h)
        for(i=0;i<N;i++)
            buffer[i][pos_N] = false;
    if(!w)
        for(i=0;i<N;i++)
            buffer[pos_N][i] = false;
    return 0;
}
int scan(int N,int pos_N)
{
    BOOL h = true;
    BOOL w = true;
    if(pos_N == N)
        return 0;
    // Do single scan
    scan_to_end(&h,&w,N,pos_N);
    // Scan all recursive before changeing data
    scan(N,pos_N+1);
    // Set the result of the scan
    set_line(h,w,N,pos_N);
    return 0;
}
int main(void)
{
    printf("Old matrix\n");
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[0][0],(WORD)buffer[0][1],(WORD)buffer[0][2],(WORD)buffer[0][3],(WORD)buffer[0][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[1][0],(WORD)buffer[1][1],(WORD)buffer[1][2],(WORD)buffer[1][3],(WORD)buffer[1][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[2][0],(WORD)buffer[2][1],(WORD)buffer[2][2],(WORD)buffer[2][3],(WORD)buffer[2][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[3][0],(WORD)buffer[3][1],(WORD)buffer[3][2],(WORD)buffer[3][3],(WORD)buffer[3][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[4][0],(WORD)buffer[4][1],(WORD)buffer[4][2],(WORD)buffer[4][3],(WORD)buffer[4][4]);
    scan(5,0);
    printf("New matrix\n");
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[0][0],(WORD)buffer[0][1],(WORD)buffer[0][2],(WORD)buffer[0][3],(WORD)buffer[0][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[1][0],(WORD)buffer[1][1],(WORD)buffer[1][2],(WORD)buffer[1][3],(WORD)buffer[1][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[2][0],(WORD)buffer[2][1],(WORD)buffer[2][2],(WORD)buffer[2][3],(WORD)buffer[2][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[3][0],(WORD)buffer[3][1],(WORD)buffer[3][2],(WORD)buffer[3][3],(WORD)buffer[3][4]);
    printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[4][0],(WORD)buffer[4][1],(WORD)buffer[4][2],(WORD)buffer[4][3],(WORD)buffer[4][4]);
    system( "pause" );
    return 0;
}

Điều này quét trong một mô hình như:

s,s,s,s,s
s,0,0,0,0
s,0,0,0,0
s,0,0,0,0
s,0,0,0,0


0,s,0,0,0
s,s,s,s,s
0,s,0,0,0
0,s,0,0,0
0,s,0,0,0

và như thế

Và sau đó thay đổi các giá trị trong mẫu này khi trả về từng chức năng quét. (Từ dưới lên):

0,0,0,0,c
0,0,0,0,c
0,0,0,0,c
0,0,0,0,c
c,c,c,c,c


0,0,0,c,0
0,0,0,c,0
0,0,0,c,0
c,c,c,c,c
0,0,0,c,0

và như thế


Tôi đoán điều này không đúng, vì bạn vẫn sử dụng nhiều hơn hai booleans trên ngăn xếp của mình.
csl

Khi tôi buồn sắp xếp hai booleans. Đây là lần gần nhất tôi có thể nghĩ đến thông số kỹ thuật anh ấy cung cấp. Tôi rất thích nhìn thấy một giải pháp thực tế ở đây. Nếu nó là fesable.
eaanon01

Tôi không nghĩ rằng các yêu cầu đề cập đến việc phát triển ngăn xếp. Tôi nghĩ rằng đây là một giải pháp hoàn toàn hợp lệ.
Adam

Đó là điều khó khăn của tôi là tốt. Nhưng tôi không thể chắc chắn cho đến khi ai đó đăng một giải pháp tốt hơn. Ít nhất giải pháp của tôi là có thể biên dịch được và có thể được xác minh bởi bất cứ ai. :) ... Tôi không tìm thấy mã psudo cho các vấn đề thực tế. Thnx
eaanon01

1

Được rồi đây là một giải pháp mà

  • chỉ sử dụng thêm một giá trị dài để lưu trữ làm việc.
  • sử dụng không đệ quy.
  • một lượt chỉ có N, thậm chí không có N * N.
  • sẽ hoạt động cho các giá trị khác của N nhưng sẽ cần #defines mới.
#include <stdio.h>
#define BIT30 (1<<24)
#define COLMASK 0x108421L
#define ROWMASK 0x1fL
unsigned long long STARTGRID = 
((0x10 | 0x0 | 0x4 | 0x2 | 0x0) << 20) |
((0x00 | 0x8 | 0x4 | 0x2 | 0x0) << 15) |
((0x10 | 0x8 | 0x4 | 0x2 | 0x1) << 10) |
((0x10 | 0x0 | 0x4 | 0x2 | 0x1) << 5) |
((0x10 | 0x8 | 0x4 | 0x2 | 0x1) << 0);


void dumpGrid (char* comment, unsigned long long theGrid) {
    char buffer[1000];
    buffer[0]='\0';
    printf ("\n\n%s\n",comment);
    for (int j=1;j<31; j++) {
        if (j%5!=1)
            printf( "%s%s", ((theGrid & BIT30)==BIT30)? "1" : "0",(((j%5)==0)?"\n" : ",") );    
        theGrid = theGrid << 1;
    }
}

int main (int argc, const char * argv[]) {
    unsigned long long rowgrid = STARTGRID;
    unsigned long long colGrid = rowgrid;

    unsigned long long rowmask = ROWMASK;
    unsigned long long colmask = COLMASK;

    dumpGrid("Initial Grid", rowgrid);
    for (int i=0; i<5; i++) {
        if ((rowgrid & rowmask)== rowmask) rowgrid |= rowmask;
        else rowgrid &= ~rowmask;
        if ((colGrid & colmask) == colmask) colmask |= colmask;
        else colGrid &=  ~colmask;
        rowmask <<= 5;
        colmask <<= 1;
    }
    colGrid &= rowgrid;
    dumpGrid("RESULT Grid", colGrid);
    return 0;
    }

Đó là một giải pháp tốt đẹp để chắc chắn. Và tôi cho rằng mọi giải pháp ở đây đều bỏ qua ít nhất một trong những yêu cầu. Vì vậy, có một giải pháp với giá trị tối đa được phép cho N không phải là điều tồi tệ nhất trên thế giới, vì vậy, công việc tuyệt vời này sẽ diễn ra :)
Adam

Hạn chế N đến 8 và tuyên bố điều này đáp ứng yêu cầu một lần vượt qua chỉ là sự ngu ngốc. Đây không phải là một giải pháp chung. Không có giới hạn về kích thước của N được nêu trong câu hỏi, vì vậy bạn chỉ giải quyết được một vấn đề phụ.
Draemon

nhưng tất cả các giải pháp này đều có giới hạn đối với N theo cách này hay cách khác.
AnthonyLambert

Nói rằng đó là một trong những vượt qua của N rõ ràng là hoàn toàn sai. Thậm chí chỉ cần đọc giá trị của từng vị trí trong ma trận gốc là O (N ^ 2) và điều chắc chắn nhất là phải đọc giá trị tại mỗi vị trí ít nhất một lần để có thể tính toán giải pháp. Ngay cả khi bạn lưu trữ các giá trị dưới dạng các bit đơn trong một thời gian dài, việc truy cập từng bit sẽ là O (N ^ 2) vì có các bit O (N ^ 2).
Alderath

Rõ ràng là một giá trị vượt qua RowGrid lưu trữ toàn bộ lưới và sau lần đọc đầu tiên sẽ là một trong các thanh ghi bộ xử lý cho toàn bộ thuật toán nếu trình tối ưu hóa là tốt.
AnthonyLambert

1

Thực ra. Nếu bạn chỉ muốn chạy thuật toán và in ra kết quả (nghĩa là không khôi phục chúng, thì điều này có thể dễ dàng thực hiện trong một lần. Vấn đề xảy ra khi bạn cố gắng sửa đổi mảng khi bạn đang chạy thuật toán.

Đây là giải pháp của tôi Nó chỉ liên quan đến ANDing các giá trị hàng / cột cho phần tử của một phần tử (i, j) và in ra.

#include <iostream>
#include "stdlib.h"

void process();

int dim = 5;
bool m[5][5]{{1,0,1,1,1},{0,1,1,0,1},{1,1,1,1,1},{1,1,1,1,1},{0,0,1,1,1}};


int main() {
    process();
    return 0;
}

void process() {
    for(int j = 0; j < dim; j++) {
        for(int i = 0; i < dim; i++) {
            std::cout << (
                          (m[0][j] & m[1][j] & m[2][j] & m[3][j] & m[4][j]) &
                          (m[i][0] & m[i][1] & m[i][2] & m[i][3] & m[i][4])
                          );
        }
        std::cout << std::endl;
    }
}

1

Tôi đã cố gắng giải quyết vấn đề này trong C #.

Tôi đã sử dụng hai biến vòng lặp (i và j) ngoài ma trận thực tế và n đại diện cho kích thước của nó

Logic tôi đã thử là:

  1. Tính AND cho các hàng và cols tham gia vào mỗi ô vuông đồng tâm của ma trận
  2. Lưu trữ nó trong các ô góc của nó (Tôi đã lưu trữ chúng theo thứ tự ngược chiều kim đồng hồ)
  3. Hai biến bool được sử dụng để giữ giá trị của hai góc khi đánh giá một hình vuông cụ thể.
  4. Quá trình này sẽ kết thúc khi vòng lặp bên ngoài (i) là giữa chừng.
  5. Đánh giá kết quả của các ô khác dựa trên các ô góc (đối với phần còn lại của i). Bỏ qua các tế bào góc trong quá trình này.
  6. Khi tôi đạt đến n, tất cả các ô sẽ có kết quả ngoại trừ các ô góc.
  7. Cập nhật các ô góc. Đây là một lần lặp bổ sung cho độ dài của n / 2 khác với ràng buộc vượt qua duy nhất được đề cập trong vấn đề.

Mã số:

void Evaluate(bool [,] matrix, int n)
{
    bool tempvar1, tempvar2;

    for (var i = 0; i < n; i++)
    {
        tempvar1 = matrix[i, i];
        tempvar2 = matrix[n - i - 1, n - i - 1];

        var j = 0;

        for (j = 0; j < n; j++)
        {
            if ((i < n/2) || (((n % 2) == 1) && (i == n/2) && (j <= i)))
            {
                // store the row and col & results in corner cells of concentric squares
                tempvar1 &= matrix[j, i];
                matrix[i, i] &= matrix[i, j];
                tempvar2 &= matrix[n - j - 1, n - i - 1];
                matrix[n - i - 1, n - i - 1] &= matrix[n - i - 1, n - j - 1];
            }
            else
            {
                // skip corner cells of concentric squares
                if ((j == i) || (j == n - i - 1)) continue;

                // calculate the & values for rest of them
                matrix[i, j] = matrix[i, i] & matrix[n - j - 1, j];
                matrix[n - i - 1, j] = matrix[n - i - 1, n - i - 1] & matrix[n - j - 1, j];

                if ((i == n/2) && ((n % 2) == 1))
                {
                    // if n is odd
                    matrix[i, n - j - 1] = matrix[i, i] & matrix[j, n - j - 1];
                }
            }
        }

        if ((i < n/2) || (((n % 2) == 1) && (i <= n/2)))
        {
            // transfer the values from temp variables to appropriate corner cells of its corresponding square
            matrix[n - i - 1, i] = tempvar1;
            matrix[i, n - i - 1] = tempvar2;
        }
        else if (i == n - 1)
        {
            // update the values of corner cells of each concentric square
            for (j = n/2; j < n; j++)
            {
                tempvar1 = matrix[j, j];
                tempvar2 = matrix[n - j - 1, n - j - 1];

                matrix[j, j] &= matrix[n - j - 1, j];
                matrix[n - j - 1, j] &= tempvar2;

                matrix[n - j - 1, n - j - 1] &= matrix[j, n - j - 1];
                matrix[j, n - j - 1] &= tempvar1;
            }
        }
    }
}

1

One Pass - Tôi đã duyệt qua đầu vào chỉ một lần nhưng đã sử dụng một mảng mới và chỉ có hai biến Boolean phụ.

public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine();

        boolean rowDel = false, colDel = false;
        int arr[][] = new int[n][n];
        int res[][] = new int[n][n];
        int i, j;
        for (i = 0; i < n; i++) {

            for (j = 0; j < n; j++) {
                arr[i][j] = sc.nextInt();
                res[i][j] = arr[i][j];  
            }
        }

        for (i = 0; i < n; i++) {

            for (j = 0; j < n; j++) {
                if (arr[i][j] == 0)
                    colDel = rowDel = true; //See if we have to delete the
                                            //current row and column
                if (rowDel == true){
                    res[i] = new int[n];
                    rowDel = false;
                }
                if(colDel == true){
                    for (int k = 0; k < n; k++) {
                        res[k][j] = 0;
                    }
                    colDel = false;
                }

            }

        }

        for (i = 0; i < n; i++) {

            for (j = 0; j < n; j++) {
                System.out.print(res[i][j]);
            }
            System.out.println();
        }
        sc.close();

    }

0

Mặc dù không thể đưa ra các ràng buộc, cách hiệu quả nhất về không gian là bằng cách di chuyển ma trận theo kiểu hàng / cột xen kẽ, xen kẽ, sẽ tạo ra một mô hình tương tự như đặt các viên gạch theo kiểu zig-zag:

-----
|----
||---
|||--
||||-

Sử dụng điều này, bạn sẽ đi vào từng hàng / cột, như được chỉ ra và nếu bạn gặp 0 bất cứ lúc nào, hãy đặt biến boolean và đi lại hàng / cột đó, đặt các mục nhập thành 0 khi bạn đi.

Điều này sẽ không cần thêm bộ nhớ và sẽ chỉ sử dụng một biến boolean. Thật không may, nếu cạnh "xa" được đặt thành 0, đó là trường hợp xấu nhất và bạn đi bộ toàn bộ mảng hai lần.


Tôi có thể sai, nhưng bạn có chắc điều này hoạt động? Khi bạn đang thực hiện cột thứ 3, hãy nói, làm thế nào để bạn biết liệu giá trị ở đầu của nó, ở hàng đầu tiên, là 1 hay 0 trước khi bạn xử lý hàng đầu tiên?
Steve Jessop

Bạn không biết, nhưng bạn cũng không cần. Nếu là 0, toàn bộ cột cần bằng 0. Nếu giá trị trên hàng trước là 1, bạn biết rằng tất cả các hàng phía trên nó là 1 (và luôn luôn là).
Dave Sherohman

0

tạo ma trận kết quả và đặt tất cả các giá trị thành 1. đi qua ma trận dữ liệu ngay khi gặp 0, đặt cột hàng ma trận kết quả thành 0

Khi kết thúc lượt đi đầu tiên, ma trận kết quả sẽ có câu trả lời đúng.

Trông khá đơn giản. Có một mẹo tôi đang thiếu? Bạn không được phép sử dụng một tập kết quả?

BIÊN TẬP:

Trông giống như một hàm F #, nhưng điều đó là gian lận một chút vì mặc dù bạn đang thực hiện một lần duy nhất, chức năng này có thể được đệ quy.

Có vẻ như người phỏng vấn đang cố gắng tìm hiểu nếu bạn biết lập trình chức năng.


1
Sử dụng một tập kết quả sẽ có thêm bộ nhớ.
cdeszaq

Lập trình chức năng sẽ không sửa đổi các mảng ban đầu tại chỗ.
Svante

0

Vâng, tôi đã đưa ra một giải pháp một lần, tại chỗ (không đệ quy) bằng cách sử dụng 4 bool và 2 bộ đếm vòng lặp. Tôi đã không quản lý để giảm nó xuống còn 2 bool và 2 ints, nhưng tôi sẽ không ngạc nhiên nếu điều đó là có thể. Nó thực hiện khoảng 3 lần đọc và 3 lần ghi của mỗi ô và nó phải là O (N ^ 2). tuyến tính trong kích thước mảng.

Mất vài giờ để giải quyết vấn đề này - tôi không muốn phải nghĩ ra nó dưới áp lực của một cuộc phỏng vấn! Nếu tôi đã tạo ra một booboo, tôi quá mệt mỏi để phát hiện ra nó ...

Ừm ... Tôi đang chọn định nghĩa "vượt qua một lần" là thực hiện một lần quét qua ma trận, thay vì chạm vào từng giá trị một lần! :-)

#include <stdio.h>
#include <memory.h>

#define SIZE    5

typedef unsigned char u8;

u8 g_Array[ SIZE ][ SIZE ];

void Dump()
{
    for ( int nRow = 0; nRow < SIZE; ++nRow )
    {
        for ( int nColumn = 0; nColumn < SIZE; ++nColumn )
        {
            printf( "%d ", g_Array[ nRow ][ nColumn ] );
        }
        printf( "\n" );
    }
}

void Process()
{
    u8 fCarriedAlpha = true;
    u8 fCarriedBeta = true;
    for ( int nStep = 0; nStep < SIZE; ++nStep )
    {
        u8 fAlpha = (nStep > 0) ? g_Array[ nStep-1 ][ nStep ] : true;
        u8 fBeta = (nStep > 0) ? g_Array[ nStep ][ nStep - 1 ] : true;
        fAlpha &= g_Array[ nStep ][ nStep ];
        fBeta &= g_Array[ nStep ][ nStep ];
        g_Array[ nStep-1 ][ nStep ] = fCarriedBeta;
        g_Array[ nStep ][ nStep-1 ] = fCarriedAlpha;
        for ( int nScan = nStep + 1; nScan < SIZE; ++nScan )
        {
            fBeta &= g_Array[ nStep ][ nScan ];
            if ( nStep > 0 )
            {
                g_Array[ nStep ][ nScan ] &= g_Array[ nStep-1 ][ nScan ];
                g_Array[ nStep-1][ nScan ] = fCarriedBeta;
            }

            fAlpha &= g_Array[ nScan ][ nStep ];
            if ( nStep > 0 )
            {
                g_Array[ nScan ][ nStep ] &= g_Array[ nScan ][ nStep-1 ];
                g_Array[ nScan ][ nStep-1] = fCarriedAlpha;
            }
        }

        g_Array[ nStep ][ nStep ] = fAlpha & fBeta;

        for ( int nScan = nStep - 1; nScan >= 0; --nScan )
        {
            g_Array[ nScan ][ nStep ] &= fAlpha;
            g_Array[ nStep ][ nScan ] &= fBeta;
        }
        fCarriedAlpha = fAlpha;
        fCarriedBeta = fBeta;
    }
}

int main()
{
    memset( g_Array, 1, sizeof(g_Array) );
    g_Array[0][1] = 0;
    g_Array[0][4] = 0;
    g_Array[1][0] = 0;
    g_Array[1][4] = 0;
    g_Array[3][1] = 0;

    printf( "Input:\n" );
    Dump();
    Process();
    printf( "\nOutput:\n" );
    Dump();

    return 0;
}

0

tôi hy vọng bạn thích giải pháp c # 1 pass của tôi

bạn có thể truy xuất một phần tử bằng O (1) và chỉ cần khoảng trắng của một hàng và một cột của ma trận

bool[][] matrix =
{
    new[] { true, false, true, true, false }, // 10110
    new[] { false, true, true, true, false }, // 01110
    new[] { true, true, true, true, true },   // 11111
    new[] { true, false, true, true, true },  // 10111
    new[] { true, true, true, true, true }    // 11111
};

int n = matrix.Length;
bool[] enabledRows = new bool[n];
bool[] enabledColumns = new bool[n];

for (int i = 0; i < n; i++)
{
    enabledRows[i] = true;
    enabledColumns[i] = true;
}

for (int rowIndex = 0; rowIndex < n; rowIndex++)
{
    for (int columnIndex = 0; columnIndex < n; columnIndex++)
    {
        bool element = matrix[rowIndex][columnIndex];
        enabledRows[rowIndex] &= element;
        enabledColumns[columnIndex] &= element;
    }
}

for (int rowIndex = 0; rowIndex < n; rowIndex++)
{
    for (int columnIndex = 0; columnIndex < n; columnIndex++)
    {
        bool element = enabledRows[rowIndex] & enabledColumns[columnIndex];
        Console.Write(Convert.ToInt32(element));
    }
    Console.WriteLine();
}

/*
    00000
    00000
    00110
    00000
    00110
*/

Tôi nghĩ vấn đề duy nhất có thể là bạn đang sử dụng hai mảng dữ liệu bổ sung để thực hiện công việc này. Một trong những quy định là không sử dụng thêm bộ nhớ. Nhưng mặc dù tốt đẹp! về cơ bản đây là những gì tôi đã làm trong câu trả lời của mình :)
Kenny Cason

0

1 lượt, 2 booleans. Tôi chỉ phải giả sử các chỉ số nguyên trong các lần lặp không được tính.

Đây không phải là một giải pháp hoàn chỉnh nhưng tôi không thể vượt qua điểm này.

Nếu tôi chỉ có thể xác định xem 0 là 0 gốc hay 1 đã được chuyển đổi thành 0 thì tôi sẽ không phải sử dụng -1 và điều này sẽ hoạt động.

Đầu ra của tôi là như thế này:

-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

Tính nguyên bản của phương pháp của tôi là sử dụng nửa đầu kiểm tra hàng hoặc cột để xác định xem nó có chứa 0 và nửa cuối để đặt giá trị hay không - điều này được thực hiện bằng cách nhìn vào x và width-x rồi y và chiều cao -y trong mỗi lần lặp. Dựa trên kết quả của nửa lần lặp đầu tiên, nếu tìm thấy 0 trong hàng hoặc cột, tôi sử dụng nửa lần lặp cuối để thay đổi 1 thành -1.

Tôi chỉ nhận ra điều này có thể được thực hiện chỉ với 1 boolean để lại 1 đến ...?

Tôi đang đăng bài này với hy vọng ai đó có thể nói: "Ah, cứ làm đi ..." (Và tôi đã dành quá nhiều thời gian cho nó để không đăng.)

Đây là mã trong VB:

Dim D(,) As Integer = {{1, 0, 1, 1, 1}, {0, 1, 1, 0, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {0, 0, 1, 1, 1}}

Dim B1, B2 As Boolean

For y As Integer = 0 To UBound(D)

    B1 = True : B2 = True

    For x As Integer = 0 To UBound(D)

        // Scan row for 0's at x and width - x positions. Halfway through I'll konw if there's a 0 in this row.
        //If a 0 is found set my first boolean to false.
        If x <= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
            If D(x, y) = 0 Or D(UBound(D) - x, y) = 0 Then B1 = False
        End If

        //If the boolean is false then a 0 in this row was found. Spend the last half of this loop
        //updating the values. This is where I'm stuck. If I change a 1 to a 0 it will cause the column
        //scan to fail. So for now I change to a -1. If there was a way to change to 0 yet later tell if
        //the value had changed this would work.
        If Not B1 Then
            If x >= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
                If D(x, y) = 1 Then D(x, y) = -1
                If D(UBound(D) - x, y) = 1 Then D(UBound(D) - x, y) = -1
            End If
        End If

        //These 2 block do the same as the first 2 blocks but I switch x and y to do the column.
        If x <= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
            If D(y, x) = 0 Or D(y, UBound(D) - x) = 0 Then B2 = False
        End If

        If Not B2 Then
            If x >= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
                If D(y, x) = 1 Then D(y, x) = -1
                If D(y, UBound(D) - x) = 1 Then D(y, UBound(D) - x) = -1
            End If
        End If

    Next
Next

0

Không ai đang sử dụng các hình thức nhị phân? vì nó chỉ có 1 và 0. Chúng ta có thể sử dụng các vectơ nhị phân.

def set1(M, N):
    '''Set 1/0s on M according to the rules.

    M is a list of N integers. Each integer represents a binary array, e.g.,
    000100'''
    ruler = 2**N-1
    for i,v in enumerate(M):
        ruler = ruler & M[i]
        M[i] = M[i] if M[i]==2**N-1 else 0  # set i-th row to all-0 if not all-1s
    for i,v in enumerate(M):
        if M[i]: M[i] = ruler
    return M

Đây là bài kiểm tra:

M = [ 0b10110,
      0b01110,
      0b11111,
      0b10111,
      0b11111 ]

print "Before..."
for i in M: print "{:0=5b}".format(i)

M = set1(M, len(M))
print "After..."
for i in M: print "{:0=5b}".format(i)

Và đầu ra:

Before...
10110
01110
11111
10111
11111
After...
00000
00000
00110
00000
00110

0

Bạn có thể làm một cái gì đó như thế này để sử dụng một lượt nhưng ma trận đầu vào và đầu ra:

output(x,y) = col(xy) & row(xy) == 2^n

trong đó col(xy)các bit trong cột chứa điểm xy;row(xy)là các bit trong hàng chứa điểm xy. nlà kích thước của ma trận.

Sau đó chỉ cần lặp qua đầu vào. Có thể mở rộng để có không gian hiệu quả hơn?


0

Một ma trận quét, hai booleans, không đệ quy.

Làm thế nào để tránh đường chuyền thứ hai? Vượt qua thứ hai là cần thiết để xóa các hàng hoặc cột khi số 0 xuất hiện ở cuối của chúng.

Tuy nhiên, vấn đề này có thể được giải quyết, bởi vì khi chúng tôi quét hàng #i, chúng tôi đã biết trạng thái hàng cho hàng # i-1. Vì vậy, trong khi chúng tôi đang quét hàng #i, chúng tôi có thể đồng thời xóa hàng # i-1 nếu cần.

Giải pháp tương tự hoạt động cho các cột, nhưng chúng ta cần quét đồng thời các hàng và cột trong khi dữ liệu không bị thay đổi bởi lần lặp tiếp theo.

Hai booleans được yêu cầu lưu trữ trạng thái của hàng đầu tiên và cột đầu tiên, bởi vì các giá trị của chúng sẽ bị thay đổi trong quá trình thực hiện phần chính của thuật toán.

Để tránh thêm nhiều booleans, chúng tôi đang lưu trữ cờ "xóa" cho các hàng và cột trong hàng và cột đầu tiên của ma trận.

public void Run()
{
    const int N = 5;

    int[,] m = new int[N, N] 
                {{ 1, 0, 1, 1, 0 },
                { 1, 1, 1, 1, 0 },
                { 1, 1, 1, 1, 1 },
                { 1, 0, 1, 1, 1 },
                { 1, 1, 1, 1, 1 }};

    bool keepFirstRow = (m[0, 0] == 1);
    bool keepFirstColumn = keepFirstRow;

    for (int i = 1; i < N; i++)
    {
        keepFirstRow = keepFirstRow && (m[0, i] == 1);
        keepFirstColumn = keepFirstColumn && (m[i, 0] == 1);
    }

    Print(m); // show initial setup

    m[0, 0] = 1; // to protect first row from clearing by "second pass"

    // "second pass" is performed over i-1 row/column, 
    // so we use one more index just to complete "second pass" over the 
    // last row/column
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            // "first pass" - searcing for zeroes in row/column #i
            // when i = N || j == N it is additional pass for clearing 
            // the previous row/column
            // j >= i because cells with j < i may be already modified 
            // by "second pass" part
            if (i < N && j < N && j >= i) 
            {
                m[i, 0] &= m[i, j];
                m[0, j] &= m[i, j];

                m[0, i] &= m[j, i];
                m[j, 0] &= m[j, i];
            }

            // "second pass" - clearing the row/column scanned 
            // in the previous iteration
            if (m[i - 1, 0] == 0 && j < N)
            {
                m[i - 1, j] = 0;
            }

            if (m[0, i - 1] == 0 && j < N)
            {
                m[j, i - 1] = 0;
            }
        }

        Print(m);
    }

    // Clear first row/column if needed
    if (!keepFirstRow || !keepFirstColumn)
    {
        for (int i = 0; i < N; i++)
        {
            if (!keepFirstRow)
            {
                m[0, i] = 0;
            }
            if (!keepFirstColumn)
            {
                m[i, 0] = 0;
            }
        }
    }

    Print(m);

    Console.ReadLine();
}

private static void Print(int[,] m)
{
    for (int i = 0; i < m.GetLength(0); i++)
    {
        for (int j = 0; j < m.GetLength(1); j++)
        {
            Console.Write(" " + m[i, j]);
        }
        Console.WriteLine();
    }
    Console.WriteLine();
}

0

có vẻ như các công trình sau không có yêu cầu không gian bổ sung:

lưu ý đầu tiên rằng nhân các phần tử của hàng nhân với các phần tử của dòng trong đó một phần tử là, cho giá trị mong muốn.

Để không sử dụng bất kỳ không gian bổ sung nào (không tạo ma trận mới và điền vào nó mà thay vào đó áp dụng các thay đổi trực tiếp cho ma trận), hãy bắt đầu trên cùng bên trái của ma trận và thực hiện tính toán cho bất kỳ ma trận ixi nào ("bắt đầu" tại (0 , 0)) trước khi xem xét bất kỳ yếu tố nào với bất kỳ chỉ số nào> i.

hy vọng điều này hoạt động (testet havent)


Có vẻ là không chính xác. Giả sử rằng hàng 0 chỉ có 1 giá trị. Nếu giá trị cuối cùng bạn đặt cho (0,0) là 0, thì sau đó bạn sẽ đặt hàng hoàn chỉnh thành 0, điều này không nhất thiết đúng. Bạn thực sự cần lưu trữ 2 giá trị trên mỗi ô để thực hiện kiểu lập trình động, sử dụng nguyên tắc của bạn.
Eyal Schneider

chắc chắn, bạn đã đúng Thay vì lưu trữ hai giá trị, tôi cũng có thể sử dụng khả năng hiển thị thứ ba, ví dụ -1, là viết tắt của các ô có 1 trong ma trận "cũ" mà cuối cùng sẽ được thay thế bằng 0. Tất nhiên, theo cách đó, người ta phải tuyệt đối các giá trị sau khi nhân. Cuối cùng, tất cả -1 được thay thế bằng 0.
DFF

0

Đây là TESTED cho N khác nhau trong C ++, và là:
ONE PASS , HAI bools , không đệ quy , không có ký ức EXTRA , giữ cho N ARBITRARLY LỚN
(Cho đến nay không ai trong số các giải pháp ở đây làm TẤT CẢ trong số này.)

Cụ thể hơn, tôi đang sử dụng hai bộ đếm vòng lặp là ổn. Tôi có hai ký hiệu không dấu, chỉ tồn tại thay vì được tính toán mỗi lần để dễ đọc. Khoảng thời gian của vòng lặp bên ngoài là [0, N] và khoảng thời gian của vòng lặp bên trong là [1, n - 1]. Câu lệnh switch nằm trong vòng lặp chủ yếu tồn tại để cho thấy rất rõ rằng nó thực sự chỉ là một lượt.

Chiến lược thuật toán:

Thủ thuật đầu tiên là cho chúng tôi một hàng và một cột từ chính ma trận để tích lũy nội dung của ma trận, bộ nhớ này sẽ có sẵn bằng cách giảm tải tất cả những gì chúng ta thực sự cần biết từ hàng đầu tiên và cột thành hai booleans. Bí quyết thứ hai là lấy hai lần ra khỏi một, bằng cách sử dụng tính đối xứng của ma trận con và các chỉ số của nó.

Tóm tắt thuật toán:

  • Quét hàng đầu tiên và lưu trữ nếu tất cả chúng đều là boolean, thực hiện tương tự cho cột đầu tiên lưu trữ kết quả trong boolean thứ hai.
  • Đối với ma trận phụ không bao gồm hàng đầu tiên và cột đầu tiên: lặp qua, từ trái sang phải, từ trên xuống dưới, như người ta sẽ đọc một đoạn văn. Khi truy cập từng phần tử, cũng truy cập phần tử tương ứng sẽ được truy cập nếu truy cập vào ma trận phụ ngược lại. Đối với mỗi phần tử được truy cập VÀ giá trị của nó vào nơi hàng của nó đi qua cột đầu tiên và cũng VÀ giá trị của nó vào nơi cột của nó đi qua hàng đầu tiên.
  • Khi đã đạt đến tâm của ma trận con, tiếp tục truy cập đồng thời hai phần tử như trên. Tuy nhiên, bây giờ đặt giá trị của các phần tử được truy cập thành AND nơi hàng của nó đi qua cột đầu tiên và nơi cột của nó đi qua hàng đầu tiên. Sau này, ma trận con đã hoàn thành.
  • Sử dụng hai biến boolean được tính toán tại cầu xin để đặt hàng đầu tiên và cột đầu tiên cho các giá trị chính xác của chúng.

Thực hiện C ++ tạm thời:

template<unsigned n>
void SidewaysAndRowColumn(int((&m)[n])[n]) {
    bool fcol = m[0][0] ? true : false;
    bool frow = m[0][0] ? true : false;
    for (unsigned d = 0; d <= n; ++d) {
        for (unsigned i = 1; i < n; ++i) {
            switch (d) {
                case 0:
                    frow    = frow && m[d][i];
                    fcol    = fcol && m[i][d];
                    break;
                default:
                {
                    unsigned const rd = n - d;
                    unsigned const ri = n - i;
                    if (d * n + i < rd * n + ri)
                    {
                        m[ d][ 0] &= m[ d][ i];
                        m[ 0][ d] &= m[ i][ d];
                        m[ 0][ i] &= m[ d][ i];
                        m[ i][ 0] &= m[ i][ d];
                        m[rd][ 0] &= m[rd][ri];
                        m[ 0][rd] &= m[ri][rd];
                        m[ 0][ri] &= m[rd][ri];
                        m[ri][ 0] &= m[ri][rd];
                    }
                    else
                    {
                        m[ d][ i] = m[ d][0] & m[0][ i];
                        m[rd][ri] = m[rd][0] & m[0][ri];
                    }
                    break;
                }
                case n:
                    if (!frow)
                        m[0][i] = 0;
                    if (!fcol)
                        m[i][0] = 0;
            };
        }
    }
    m[0][0] = (frow && fcol) ? 1 : 0;
}

0

Ok, tôi nhận ra rằng nó không hoàn toàn khớp, nhưng tôi đã vượt qua nó bằng một bool và byte thay vì hai bool ... đóng. Tôi cũng sẽ không chứng minh cho hiệu quả của nó nhưng những loại câu hỏi này thường đòi hỏi ít hơn các giải pháp tối ưu.

private static void doIt(byte[,] matrix)
{
    byte zeroCols = 0;
    bool zeroRow = false;

    for (int row = 0; row <= matrix.GetUpperBound(0); row++)
    {
        zeroRow = false;
        for (int col = 0; col <= matrix.GetUpperBound(1); col++)
        {
            if (matrix[row, col] == 0)
            {

                zeroRow = true;
                zeroCols |= (byte)(Math.Pow(2, col));

                // reset this column in previous rows
                for (int innerRow = 0; innerRow < row; innerRow++)
                {
                    matrix[innerRow, col] = 0;
                }

                // reset the previous columns in this row
                for (int innerCol = 0; innerCol < col; innerCol++)
                {
                    matrix[row, innerCol] = 0;
                }
            }
            else if ((int)(zeroCols & ((byte)Math.Pow(2, col))) > 0)
            {
                matrix[row, col] = 0;
            }

            // Force the row to zero
            if (zeroRow) { matrix[row, col] = 0; }
        }
    }
}

0

Bạn có thể sắp xếp thực hiện trong một lượt - nếu bạn không tính truy cập ma trận theo thứ tự truy cập ngẫu nhiên, điều này sẽ loại bỏ các lợi ích của việc thực hiện một lượt ở vị trí đầu tiên (băng thông bộ nhớ đệm / băng thông bộ nhớ).

[chỉnh sửa: đơn giản, nhưng giải pháp sai đã bị xóa]

Bạn sẽ có được hiệu suất tốt hơn bất kỳ phương pháp vượt qua đơn nào bằng cách thực hiện theo hai lần: một để tích lũy thông tin hàng / cột và một để áp dụng nó. Mảng (theo thứ tự chính hàng) được truy cập mạch lạc; đối với các mảng vượt quá kích thước bộ đệm (nhưng có hàng có thể vừa trong bộ đệm), dữ liệu nên được đọc từ bộ nhớ hai lần và được lưu trữ một lần:

void fixmatrix2(int M[][], int rows, int cols) {
    bool clearZeroRow= false;
    bool clearZeroCol= false;
    for(int j=0; j < cols; ++j) {
        if( ! M[0][j] ) {
            clearZeroRow= true;
        }
    }
    for(int i=1; i < rows; ++i) { // scan/accumulate pass
        if( ! M[i][0] ) {
            clearZeroCol= true;
        }
        for(int j=1; j < cols; ++j) {
            if( ! M[i][j] ) {
                M[0][j]= 0;
                M[i][0]= 0;
            }
        }
    }
    for(int i=1; i < rows; ++i) { // update pass
        if( M[i][0] ) {
            for(int j=0; j < cols; ++j) {
                if( ! M[j][0] ) {
                    M[i][j]= 0;
                }
            }
        } else {
            for(int j=0; j < cols; ++j) {
                M[i][j]= 0;
            }
        }
        if(clearZeroCol) {
            M[i][0]= 0;
        }
    }
    if(clearZeroRow) {
        for(int j=0; j < cols; ++j) {
            M[0][j]= 0;
        }
    }
}

0

Giải pháp đơn giản nhất tôi có thể nghĩ đến được dán bên dưới. Logic là ghi lại hàng và cột nào để đặt 0 trong khi lặp.

import java.util.HashSet;
import java.util.Set;

public class MatrixExamples {
    public static void zeroOut(int[][] myArray) {
        Set<Integer> rowsToZero = new HashSet<>();
        Set<Integer> columnsToZero = new HashSet<>();

        for (int i = 0; i < myArray.length; i++) { 
            for (int j = 0; j < myArray.length; j++) {
                if (myArray[i][j] == 0) {
                    rowsToZero.add(i);
                    columnsToZero.add(j);
                }
            }
        }

        for (int i : rowsToZero) {
            for (int j = 0; j < myArray.length; j++) {
                myArray[i][j] = 0;
            }
        }

        for (int i : columnsToZero) {
            for (int j = 0; j < myArray.length; j++) {
                myArray[j][i] = 0;
            }
        }

        for (int i = 0; i < myArray.length; i++) { // record which rows and                                             // columns will be zeroed
            for (int j = 0; j < myArray.length; j++) {
                System.out.print(myArray[i][j] + ",");
            if(j == myArray.length-1)
                System.out.println();
            }
        }

    }

    public static void main(String[] args) {
        int[][] a = { { 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 } };
        zeroOut(a);
    }
}

0

Đây là triển khai Ruby của tôi với bài kiểm tra bao gồm, Điều này sẽ chiếm không gian O (MN). Nếu chúng ta muốn cập nhật theo thời gian thực (muốn hiển thị kết quả khi chúng ta tìm thấy số 0 thay vì chờ vòng lặp đầu tiên tìm số không), chúng ta có thể tạo một biến lớp khác như @outputbất cứ khi nào chúng ta tìm thấy số 0 chúng ta cập nhật @outputvà không @input.

require "spec_helper"


class Matrix
    def initialize(input)
        @input  = input
        @zeros  = []
    end

    def solve
        @input.each_with_index do |row, i|          
            row.each_with_index do |element, j|                             
                @zeros << [i,j] if element == 0
            end
        end

        @zeros.each do |x,y|
            set_h_zero(x)
            set_v_zero(y)
        end

        @input
    end


    private 

    def set_h_zero(row)     
        @input[row].map!{0}     
    end

    def set_v_zero(col)
        @input.size.times do |r|
            @input[r][col] = 0
        end
    end
end


describe "Matrix" do
  it "Should set the row and column of Zero to Zeros" do
    input =  [[1, 3, 4, 9, 0], 
              [0, 3, 5, 0, 8], 
              [1, 9, 6, 1, 9], 
              [8, 3, 2, 0, 3]]

    expected = [[0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0],
                [0, 9, 6, 0, 0],
                [0, 0, 0, 0, 0]]

    matrix = Matrix.new(input)

    expect(matrix.solve).to eq(expected)
  end
end

0

Mã dưới đây tạo ra một ma trận có kích thước m, n. Đầu tiên quyết định kích thước của ma trận. Tôi muốn điền vào ma trận [m] [n] một cách ngẫu nhiên với các số trong khoảng từ 0..10. Sau đó tạo một ma trận khác có cùng kích thước và điền nó với -1s (ma trận cuối cùng). Sau đó lặp lại qua ma trận ban đầu để xem bạn có trúng 0. Khi bạn nhấn vào vị trí (x, y), hãy chuyển đến ma trận cuối cùng và điền vào hàng x với 0s và cột y bằng 0s. Cuối cùng đọc qua ma trận cuối cùng, nếu giá trị là -1 (giá trị ban đầu) sao chép giá trị trong cùng một vị trí của ma trận ban đầu để cuối cùng.

public static void main(String[] args) {
    int m = 5;
    int n = 4;
    int[][] matrixInitial = initMatrix(m, n); // 5x4 matrix init randomly
    int[][] matrixFinal = matrixNull(matrixInitial, m, n); 
    for (int i = 0; i < m; i++) {
        System.out.println(Arrays.toString(matrixFinal[i]));
    }
}

public static int[][] matrixNull(int[][] matrixInitial, int m, int n) {
    int[][] matrixFinal = initFinal(m, n); // create a matrix with mxn and init it with all -1
    for (int i = 0; i < m; i++) { // iterate in initial matrix
        for (int j = 0; j < n; j++) {
            if(matrixInitial[i][j] == 0){ // if a value is 0 make rows and columns 0
                makeZeroX(matrixFinal, i, j, m, n); 
            }
        }
    }

    for (int i = 0; i < m; i++) { // if value is -1 (original) copy from initial
        for (int j = 0; j < n; j++) {
            if(matrixFinal[i][j] == -1) {
                matrixFinal[i][j] = matrixInitial[i][j];
            }
        }
    }
    return matrixFinal;
}

private static void makeZeroX(int[][] matrixFinal, int x, int y, int m, int n) {
        for (int j = 0; j < n; j++) { // make all row 0
            matrixFinal[x][j] = 0;
        }
        for(int i = 0; i < m; i++) { // make all column 0
            matrixFinal[i][y] = 0; 
        }
}

private static int[][] initMatrix(int m, int n) {

    int[][] matrix = new int[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            Random rn = new Random();
            int random = rn.nextInt(10);
            matrix[i][j] = random;
        }
    }

    for (int i = 0; i < m; i++) {
        System.out.println(Arrays.toString(matrix[i]));
    }
    System.out.println("******");
    return matrix;
}

private static int[][] initFinal(int m, int n) {

    int[][] matrix = new int[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i][j] = -1;
        }
    }
    return matrix;
}

// another approach
/**
 * @param matrixInitial
 * @param m
 * @param n
 * @return
 */
private static int[][] matrixNullNew(int[][] matrixInitial, int m, int n) {
    List<Integer> zeroRowList = new ArrayList<>(); // Store rows with 0
    List<Integer> zeroColumnList = new ArrayList<>(); // Store columns with 0
    for (int i = 0; i < m; i++) { // read through the matrix when you hit 0 add the column to zeroColumnList and add
                                  // the row to zeroRowList
        for (int j = 0; j < n; j++) {
            if (matrixInitial[i][j] == 0) {
                if (!zeroRowList.contains(i)) {
                    zeroRowList.add(i);
                }
                if (!zeroColumnList.contains(j)) {
                    zeroColumnList.add(j);
                }
            }
        }
    }

    for (int a = 0; a < m; a++) {
        if (zeroRowList.contains(a)) { // if the row has 0
            for (int b = 0; b < n; b++) {
                matrixInitial[a][b] = 0; // replace all row with zero
            }
        }
    }

    for (int b = 0; b < n; b++) {
        if (zeroColumnList.contains(b)) { // if the column has 0
            for (int a = 0; a < m; a++) {
                matrixInitial[a][b] = 0; // replace all column with zero
            }
        }
    }
    return matrixInitial;
}

Bạn không đưa ra bất kỳ lời giải thích hoặc bối cảnh nào cho mã bạn đã đăng.
Aaron

Hy vọng rằng tốt hơn bây giờ. Cảm ơn đã cảnh báo. Tôi muốn giải thích thêm, nếu nó không rõ ràng cho bạn.
dùng3743369

0

đây là giải pháp của tôi Như bạn có thể thấy từ mã, được đưa ra một ma trận M * N, nó đặt toàn bộ hàng thành 0 khi nó kiểm tra số 0 trong hàng đó. Độ phức tạp thời gian của giải pháp của tôi là O (M * N). Tôi đang chia sẻ toàn bộ lớp có một mảng dân cư tĩnh để thử nghiệm và một phương thức mảng hiển thị để xem kết quả trong bàn điều khiển.

public class EntireRowSetToZero {
    static int arr[][] = new int[3][4];
    static {

    arr[0][0] = 1;
    arr[0][1] = 9;
    arr[0][2] = 2;
    arr[0][3] = 2;

    arr[1][0] = 1;
    arr[1][1] = 5;
    arr[1][2] = 88;
    arr[1][3] = 7;

    arr[2][0] = 0;
    arr[2][1] = 8;
    arr[2][2] = 4;
    arr[2][3] = 4;
}

public static void main(String[] args) {
    displayArr(EntireRowSetToZero.arr, 3, 4);
    setRowToZero(EntireRowSetToZero.arr);
    System.out.println("--------------");
    displayArr(EntireRowSetToZero.arr, 3, 4);


}

static int[][] setRowToZero(int[][] arr) {
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr[i].length; j++) {
            if(arr[i][j]==0){
                arr[i]=new int[arr[i].length];
            }
        }

    }
    return arr;
}

static void displayArr(int[][] arr, int n, int k) {

    for (int i = 0; i < n; i++) {

        for (int j = 0; j < k; j++) {
            System.out.print(arr[i][j] + " ");
        }
        System.out.println("");
    }

}

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.