it-swarm.com.de

Setzen Sie jede Zelle in der Matrix auf, wenn diese Zeile oder Spalte a enthält

Gegeben eine NxN-Matrix mit 0s und 1s. Setzen Sie jede Zeile, die einen 0 enthält, auf alle 0s und jede Spalte, die einen 0 enthält, auf alle 0s.

Zum Beispiel

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

führt in

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

Ein Microsoft-Ingenieur hat mir erzählt, dass es eine Lösung gibt, die keinen zusätzlichen Arbeitsspeicher erfordert, nur zwei boolesche Variablen und einen Durchlauf. Ich suche also nach dieser Antwort.

BTW, stellen Sie sich vor, es handelt sich um eine Bitmatrix, daher dürfen nur 1s und 0s in der Matrix sein.

Ok, ich bin müde, da es 3 Uhr morgens ist, aber ich habe einen ersten Versuch mit genau zwei Durchgängen auf jeder Zahl in der Matrix, also in O(NxN), und die Größe der Matrix ist linear .

Ich benutze die erste Spalte und die erste Zeile als Marker, um zu wissen, wo Zeilen/Spalten mit nur Einsen stehen. Dann gibt es die beiden Variablen l und c, die zu beachten sind, wenn die erste Zeile/Spalte alle auch 1 ist .. Die erste Zeile setzt die Markierungen und setzt den Rest auf 0 zurück.

Der zweite Durchlauf setzt 1 an Stellen, an denen Zeilen und Spalten als 1 markiert wurden, und setzt die erste Zeile/Spalte je nach l und c zurück. 

Ich bezweifle stark, dass ich in einem Durchgang durchgeführt werden kann, da Quadrate am Anfang von Quadraten am Ende abhängen. Vielleicht kann mein 2. Pass effizienter gemacht werden ...

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)
97
Piotr Lesnicki

Dies kann nicht in einem Durchgang durchgeführt werden, da ein einzelnes Bit die Bits davor und danach in beliebiger Reihenfolge beeinflusst. Egal in welcher Reihenfolge Sie das Array durchlaufen, Sie können später eine 0 durchlaufen, was bedeutet, dass Sie zurückgehen und eine vorherige 1 in eine 0 ändern müssen.

Update

Die Leute scheinen zu denken, dass man durch die Beschränkung von N auf einen festen Wert (zB 8) lösen kann, dass dies ein Durchgang ist. Nun, das ist a) der Punkt fehlt und b) nicht die ursprüngliche Frage. Ich würde keine Frage zum Sortieren stellen und erwarte eine Antwort, die "mit der Annahme begann, dass Sie nur 8 Dinge sortieren wollen ...".

Das heißt, es ist ein vernünftiger Ansatz, wenn Sie wissen, dass N tatsächlich auf 8 beschränkt ist. Meine Antwort oben beantwortet die ursprüngliche Frage, die keine solche Abfrage enthält.

15
Draemon

Meine Idee ist also, die Werte in der letzten Zeile/Spalte als Flag zu verwenden, um anzuzeigen, ob alle Werte in der entsprechenden Spalte/Zeile 1s sind.

Verwenden Sie einen Zick-Zag-Scan durch die gesamte Matrix, AUSSER der letzten Zeile/Spalte. Bei jedem Element legen Sie den Wert in der letzten Zeile/Spalte in Bezug auf das logische UND von sich selbst mit dem Wert im aktuellen Element fest. Mit anderen Worten, wenn Sie eine 0 drücken, wird die letzte Zeile/Spalte auf 0 gesetzt. Wenn Sie eine 1 angeben, wird der Wert in der letzten Zeile/Spalte nur dann 1 sein, wenn es bereits 1 war. In jedem Fall setzen Sie das aktuelle Element auf 0.

Wenn Sie fertig sind, sollte Ihre letzte Zeile/Spalte 1s haben, wenn die entsprechende Spalte/Zeile mit 1s gefüllt wurde.

Führen Sie einen linearen Scan durch die letzte Zeile und Spalte durch und suchen Sie nach 1s. Setzen Sie 1s in die entsprechenden Elemente im Hauptteil der Matrix, wobei die letzte Zeile und Spalte beide 1s sind.

Das Codieren wird schwierig sein, um einzelne Fehler usw. zu vermeiden, aber es sollte in einem Durchgang funktionieren.

10
Alastair

Ich habe hier eine Lösung, sie läuft in einem einzigen Durchgang und erledigt die gesamte Verarbeitung "an Ort und Stelle" ohne zusätzlichen Speicher (außer für das Wachstum des Stapels).

Es verwendet Rekursion, um das Schreiben von Nullen zu verzögern, was natürlich die Matrix für die anderen Zeilen und Spalten zerstören würde:

#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();
}
6
Adam

Ich denke nicht, dass es machbar ist. Wenn Sie sich auf dem ersten Quadrat befinden und der Wert 1 ist, können Sie nicht wissen, welche Werte die anderen Quadrate in derselben Zeile und Spalte haben. Sie müssen diese überprüfen und wenn es eine Null gibt, kehren Sie zum ersten Quadrat zurück und ändern Sie den Wert in Null. Ich empfehle, dies in zwei Durchgängen durchzuführen - der erste Durchlauf sammelt Informationen darüber, welche Zeilen und Spalten auf Null gesetzt werden müssen (die Informationen werden in einem Array gespeichert, daher benötigen wir zusätzlichen Speicher). Der zweite Durchgang ändert die Werte. Ich weiß, das ist nicht die Lösung, die Sie suchen, aber ich denke, es ist eine praktische Lösung. Die von Ihnen gegebenen Einschränkungen machen das Problem unlösbar.

4
Boyan

Ich kann es mit zwei Integer-Variablen und zwei Durchläufen (bis zu 32 Zeilen und Spalten ...)

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));
3
Eclipse

das Problem kann in einem Durchgang gelöst werden

speichern der Matrix in einem i X j -Array.

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 .

drucke jetzt alle Werte als 0 für Werte von i und j, die in a und b gespeichert sind. Rest der Werte sind 1, dh (3,3) (3,4) (5,3) und (5,4)

3
siddharth

Eine weitere Lösung, die zwei Durchläufe erfordert, ist die UND-Verknüpfung horizontal und vertikal:

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    

Ich dachte, ich könnte einen solchen Algorithmus unter Verwendung von Parity Bits , Hamming-Codes oder dynamischer Programmierung entwerfen, möglicherweise diese beiden Booleans als 2-Bit-Zahl verwenden, aber ich hatte bisher noch keinen Erfolg .

Können Sie bitte die Problemstellung erneut mit Ihrem Ingenieur prüfen und uns Bescheid geben? Wenn Dort is in der Tat eine Lösung ist, möchte ich das Problem weiter lösen.

1
csl

Schöne Herausforderung. Bei dieser Lösung werden nur zwei Booleans verwendet, die auf dem Stack erstellt werden. Die Booleans werden jedoch mehrmals auf dem Stack erstellt, da die Funktion rekursiv ist.

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;
}

Dies scannt in einem Muster wie:

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

und so weiter

Wenn Sie dann die Werte in diesem Muster ändern, kehren Sie zu jeder der Scanfunktionen zurück. (Prost):

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

und so weiter

1
eaanon01

Okay, das ist eine Lösung, die  

  • verwendet nur einen extra langen Wert für die Arbeitsspeicherung.
  • verwendet keine Rekursion.
  • ein Durchgang von nur N, nicht einmal N * N.
  • funktioniert für andere Werte von N, benötigt aber neue #defines.
#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;
    }
1
AnthonyLambert

Ich habe versucht, dieses Problem in C # zu lösen.

Ich habe zwei Schleifenvariablen (i und j) verwendet, abgesehen von der eigentlichen Matrix, und n repräsentiert deren Dimension

Logik, die ich versuchte, ist: 

  1. Berechnen Sie UND für die Zeilen und Spalten, die an jedem konzentrischen Quadrat der Matrix beteiligt sind 
  2. Speichern Sie es in seinen Eckzellen (ich habe sie gegen den Uhrzeigersinn gespeichert) 
  3. Zwei bool-Variablen werden verwendet, um Werte von zwei Ecken bei der Auswertung eines bestimmten Quadrats beizubehalten. 
  4. Dieser Prozess würde enden, wenn sich die äußere Schleife (i) in der Mitte befindet. 
  5. Bewerten Sie die Ergebnisse anderer Zellen basierend auf den Eckzellen (für den Rest von i). Überspringen Sie die Eckzellen während dieses Vorgangs. 
  6. Wenn i n erreicht, haben alle Zellen außer den Eckzellen ihr Ergebnis. 
  7. Aktualisieren Sie die Eckzellen. Dies ist eine zusätzliche Iteration der Länge von n/2, die von der in dem Problem genannten Einschränkung für den einzelnen Durchlauf abgesehen wird.

Code:

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
B.K

Behalten Sie eine einzige Variable, um zu verfolgen, was alle Zeilen UND-Verknüpfungen sind.

Wenn eine Zeile -1 ist (alle 1s), machen Sie die nächste Zeile zu einer Referenz auf diese Variable

Wenn eine Reihe nichts anderes ist, ist es eine 0. Sie können alles in einem Durchgang erledigen. Pseudo-Code:

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

Das sollte es in einem einzigen Durchgang tun - aber hier wird davon ausgegangen, dass N klein genug ist, damit die CPU Arithmetik für eine einzelne Zeile ausführen kann. Andernfalls müssen Sie jede Zeile durchlaufen, um zu bestimmen, ob dies alles ist Ich glaube nicht. Wenn Sie jedoch nach Algos fragen und meine Hardware nicht einschränken, würde ich meine Antwort mit "Erstellen einer CPU, die N-Bit-Arithmetik unterstützt ..." beginnen.

Hier ein Beispiel, wie dies in C möglich ist. Hinweis: Ich behaupte, dass Werte und Arr zusammen das Array darstellen, und p und numproduct mein Iterator und AND-Produktvariablen zur Implementierung des Problems sind. (Ich hätte den Arr mit Zeigerarithmetik überarbeiten können, um meine Arbeit zu bestätigen, aber einmal war genug!)

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;
}

Dies ergibt 0, 0, 6, 0, 6, was für die gegebenen Eingänge das Ergebnis ist.

Oder in PHP, wenn die Leute meinen, dass meine Stack-Spiele in C betrügen (ich schlage Ihnen vor, dass dies nicht der Fall ist, da ich die Matrix auf jede beliebige Art und Weise speichern kann):

<?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);

Fehlt mir etwas?

1
Daniel Papasian

Tatsächlich. Wenn Sie nur den Algorithmus ausführen und die Ergebnisse ausdrucken möchten (d. H. Nicht wiederherstellen), können Sie dies leicht in einem Durchgang erledigen. Das Problem tritt auf, wenn Sie versuchen, das Array während der Ausführung des Algorithmus zu ändern.

Hier ist meine Lösung. Es beinhaltet nur das ANDieren der Zeilen/Spalten-Werte für ein Givein (i, j) -Element und das Ausdrucken. 

#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
Kenny Cason

erstellen Sie eine Ergebnismatrix und setzen Sie alle Werte auf 1 . Durchlaufen Sie die Datenmatrix, sobald eine 0 auftritt, und setzen Sie die Ergebnismatrix-Zeilenspalte auf 0

Am Ende des ersten Durchlaufs hat die Ergebnismatrix die richtige Antwort.

Sieht ziemlich einfach aus. Gibt es einen Trick, den ich vermisse? Dürfen Sie keine Ergebnismenge verwenden?

BEARBEITEN:

Sieht aus wie eine F # -Funktion, aber das ist etwas schummelig, denn obwohl Sie einen einzelnen Durchlauf durchführen, kann die Funktion rekursiv sein.

Anscheinend versucht der Interviewer herauszufinden, ob Sie die funktionale Programmierung kennen.

0
mson

One Pass - Ich habe die Eingabe nur einmal durchlaufen, aber ein neues Array und nur zwei zusätzliche boolesche Variablen verwendet.

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
RahulDeep Attri

ich hoffe, Sie genießen meine 1-Pass-Lösung

sie können ein Element mit O(1) abrufen und brauchen nur den Platz einer Zeile und einer Spalte der Matrix

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
*/
0
Nick

Der folgende Code erstellt eine Matrix der Größe m, n. Bestimmen Sie zuerst die Abmessungen der Matrix. Ich wollte die Matrix [m] [n] zufällig mit Zahlen zwischen 0..10 füllen. Erstellen Sie dann eine weitere Matrix mit den gleichen Abmessungen und füllen Sie sie mit -1s (endgültige Matrix). Durchlaufen Sie dann die anfängliche Matrix, um zu sehen, ob Sie 0 drücken. Wenn Sie auf Position (x, y) klicken, gehen Sie zur letzten Matrix und füllen Sie die Zeile x mit 0 und die Spalte y mit 0. Wenn Sie am Ende die letzte Matrix gelesen haben, kopieren Sie den Wert an der gleichen Stelle der ursprünglichen Matrix, wenn der Wert -1 ist (ursprünglicher Wert).

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;
}
0
user3743369

Ok, mir ist klar, dass es nicht gerade eine Übereinstimmung ist, aber ich habe es in einem Durchgang mit einem Bool und einem Byte anstelle von zwei Bools erhalten ... close. Ich würde auch nicht für die Effizienz bürgen, aber diese Art von Fragen erfordert oft nicht optimale Lösungen.

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
Dj Wise

Niemand benutzt binäre Formen? da es nur 1 und 0 ist. Wir können binäre Vektoren verwenden.

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

Hier ist der Test:

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)

Und die Ausgabe:

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

scheint wie folgt zu arbeiten, ohne zusätzlichen Platzbedarf:

beachten Sie zunächst, dass die Multiplikation der Elemente der Zeile mit den Elementen der Zeile, in der sich ein Element befindet, den gewünschten Wert ergibt.

Um keinen zusätzlichen Speicherplatz zu verwenden (keine neue Matrix erstellen und auffüllen, sondern Änderungen direkt an der Matrix vornehmen), beginnen Sie oben links in der Matrix und führen Sie die Berechnung für jede ixi-Matrix durch (die bei (0 beginnt) , 0)), bevor ein Element mit einem Index> i betrachtet wird.

hoffe das funktioniert (havent testet)

0
D.F.F

Die einfachste Lösung, die ich mir vorstellen kann, ist unten eingefügt. Die Logik besteht darin, aufzuzeichnen, welche Zeile und Spalte während der Iteration auf Null gesetzt werden soll.

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
geekprogrammer

Ein Matrix-Scan, zwei Booleans, keine Rekursion.

So vermeiden Sie den zweiten Durchlauf? Der zweite Durchlauf ist erforderlich, um die Zeilen oder Spalten zu löschen, wenn die Null am Ende erscheint.

Dieses Problem kann jedoch gelöst werden, da beim Scannen der Zeile #i bereits der Zeilenstatus für die Zeile # i-1 bekannt ist. Während wir die Zeile #i scannen, können wir die Zeile # i-1 gleichzeitig löschen, wenn sie benötigt wird.

Dieselbe Lösung funktioniert für Spalten, aber Zeilen und Spalten müssen gleichzeitig gescannt werden, während die Daten bei der nächsten Iteration nicht geändert werden.

Zum Speichern des Status der ersten Zeile und der ersten Spalte sind zwei Booleans erforderlich, da ihre Werte während der Ausführung des Hauptteils des Algorithmus geändert werden.

Um das Hinzufügen weiterer Booleans zu vermeiden, speichern wir das Flag "clear" für die Zeilen und Spalten in der ersten Zeile und Spalte der Matrix.

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
Artemix

Sie können dies in einem Durchgang erledigen - wenn Sie nicht zählen, dass Sie auf die Matrix in zufälliger Reihenfolge zugreifen, wodurch die Vorteile eines einzigen Durchlaufs (Cache-Kohärenz/Speicherbandbreite) zunichte gemacht werden.

[edit: einfache, aber falsche Lösung gelöscht]

Sie sollten eine bessere Leistung als jede einzelne Durchlaufmethode erzielen, indem Sie sie in zwei Durchgängen durchführen: einen, um Zeilen-/Spalteninformationen zu sammeln, und einen, um sie anzuwenden. Auf das Array (in Zeile-Dur-Reihenfolge) wird kohärent zugegriffen. Bei Arrays, die die Cachegröße überschreiten (deren Zeilen jedoch in den Cache passen können), sollten die Daten zweimal aus dem Speicher gelesen und einmal gespeichert werden:

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
comingstorm

Sie können so etwas tun, um nur einen Durchlauf, aber eine Eingabe- und Ausgabematrix zu verwenden:

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

dabei ist col(xy) die Bits in der Spalte, die den Punkt xy enthält. row(xy) sind die Bits in der Zeile, die den Punkt xy enthält. n ist die Größe der Matrix.

Dann einfach die Eingabe übergehen. Möglicherweise erweiterbar, um platzsparender zu sein?

0
Warbum

Nun, ich hatte eine Single-Pass-Lösung (nicht rekursiv) mit 4 Bool und 2 Schleifenzählern. Ich habe es nicht geschafft, es auf 2 Bools und 2 Ints zu reduzieren, aber es würde mich nicht wundern, wenn es möglich wäre. Es führt ungefähr 3 Lesevorgänge und 3 Schreibvorgänge in jeder Zelle aus, und es sollte O (N ^ 2) sein, d. linear in der Arraygröße.

Ich habe ein paar Stunden gebraucht, um das hier herauszufinden. Ich möchte es nicht unter dem Druck eines Interviews haben müssen! Wenn ich ein Booboo gemacht habe, bin ich zu müde, um es zu erkennen ...

Ähm ... Ich wähle "Single-Pass" als einen Durchlauf durch die Matrix, anstatt jeden Wert einmal zu berühren! :-)

#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
David Radford

hier ist meine Lösung. Wie Sie dem Code entnehmen können, setzt er bei einer M * N-Matrix die gesamte Zeile auf Null, sobald eine Null in dieser Zeile geprüft wird. Die zeitliche Komplexität meiner Lösung ist O (M * N) ..__ Freigabe der gesamten Klasse, die über ein statisches Array zum Testen verfügt, und eine Display-Array-Methode, um das Ergebnis in der Konsole anzuzeigen. 

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("");
    }

}

}

Setzen Sie ein Flag (eine Zahl, die außerhalb der Einschränkung ist, verwende ich -1). Wenn Sie alle übereinstimmenden Zeilen und Spalten geändert haben, setzen Sie das Flag auf Null

public class Main {

        public static void main(String[] args) {


            //test case 1
            int[][] multi = new int[][]{
                    { 1, 2, 3 },
                    { 4, 0, 5 },
                    { 0, 6, 7 },
            };

            //test case 2
            int[][] multi2 = new int[][]{
                    { 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},
            };

            TwoDArraySetZero(multi2);
        }



        static  void  TwoDArraySetZero(int[][] array){

            //iterate through all elements
            for(int i = 0 ; i <= array.length-1 ; i++){
                for (int j = 0; j <= array.length-1; j++) {

                    //checking if match with zero
                    if (array[i][j] == 0){

                        //set replace with -1 all matching zero row and col if not zero
                        for (int k = 0; k <= array.length-1 ; k++) {
                            if(array[i][k] != 0 )
                                array[i][k] = -1;
                            if(array[k][j] != 0)
                                array[k][j]= -1;
                        }
                    }
                }
            }


            //print array
            for(int i = 0; i <= array.length-1; i++)
            {
                for(int j = 0; j <= array.length-1; j++)
                {
                    //replace with zero all -1

                    if(array[i][j] == -1)
                        array[i][j] = 0;

                    System.out.printf("%5d ", array[i][j]);
                }
                System.out.println();
            }

        }

    }
0
Muhammed Afsal

Dies istGETESTETfür verschiedene N in C++ und ist:
EIN PASS , ZWEI KÖPFE , KEINE RECURSION , KEIN EXTRA-SPEICHER , HALTEN FÜR ARBEITLICH GROß N
(Bisher hat keine der Lösungen ALLE davon.)

Genauer gesagt bin ich amüsant, dass zwei Schleifenzähler in Ordnung sind. Ich habe zwei const unsigned, die nur existieren und nicht jedes Mal zur besseren Lesbarkeit berechnet werden. Das Intervall der äußeren Schleife ist [0, N] und das Intervall der inneren Schleife ist [1, n - 1]. Die switch-Anweisung ist in der Schleife meistens vorhanden, um sehr deutlich zu zeigen, dass es sich tatsächlich nur um einen Durchgang handelt.

Algorithmusstrategie:

Der erste Trick besteht darin, eine Zeile und eine Spalte aus der Matrix selbst zu sammeln, um den Inhalt der Matrix zu akkumulieren. Dieser Speicher wird verfügbar, indem alles, was wir wirklich wissen müssen, aus der ersten Zeile und Spalte in zwei Booleans geladen wird. Der zweite Trick besteht darin, zwei Durchgänge aus einem herauszuholen, indem die Symmetrie der Untermatrix und ihrer Indizes verwendet wird.

Algorithmus-Übersicht:  

  • Scannen Sie die erste Zeile und speichern Sie sie, wenn sie alle in einem Boolean-Wert sind. Führen Sie dasselbe für die erste Spalte aus, und speichern Sie das Ergebnis in einem zweiten Boolean-Wert.
  • Für die Untermatrix mit Ausnahme der ersten Zeile und der ersten Spalte: Durchlaufen Sie von links nach rechts und von oben nach unten, so wie Sie einen Absatz lesen würden. Besuchen Sie bei jedem Elementbesuch auch das entsprechende Element, das Sie besuchen würden, wenn Sie die Untermatrix in umgekehrter Reihenfolge besuchen. Für jedes besuchte Element UND sein Wert in den Bereich, in dem die Zeile die erste Spalte kreuzt, und AND den Wert in den Bereich, in dem die Spalte die erste Zeile kreuzt.
  • Sobald das Zentrum der Untermatrix erreicht ist, können Sie die beiden Elemente gleichzeitig wie oben beschrieben besuchen. Setzen Sie den Wert der besuchten Elemente jedoch jetzt auf das UND, wo die Zeile die erste Spalte und die Spalte die erste Zeile kreuzt. Danach ist die Submatrix vollständig.
  • Verwenden Sie die beiden am Anfang berechneten booleschen Variablen, um die erste Zeile und die erste Spalte auf ihre korrekten Werte festzulegen.

Templatized C++ - Implementierung:

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
Apriori

1 Durchgang, 2 Booleans. Ich muss nur annehmen, dass die Ganzzahlindizes in den Iterationen nicht zählen.

Dies ist keine vollständige Lösung, aber ich kann diesen Punkt nicht bestehen.

Wenn ich nur feststellen könnte, ob eine 0 eine ursprüngliche 0 oder eine 1 ist, die in eine 0 umgewandelt wurde, müsste ich nicht -1 verwenden, und das würde funktionieren.

Meine Ausgabe ist wie folgt:

-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

Die Originalität meines Ansatzes besteht darin, die erste Hälfte der Untersuchung einer Zeile oder Spalte zu verwenden, um festzustellen, ob sie eine 0 enthält, und die letzte Hälfte, um die Werte festzulegen. Dazu werden x und width-x und dann y und height verwendet -y in jeder Iteration. Basierend auf den Ergebnissen der ersten Hälfte der Iteration, wenn eine 0 in der Zeile oder Spalte gefunden wurde, verwende ich die letzte Hälfte der Iteration, um die 1 in -1 zu ändern. 

Ich habe gerade gemerkt, dass dies mit nur einem booleschen Wert von 1 bis ...?

Ich poste dies in der Hoffnung, dass jemand sagen könnte: "Ah, mach einfach das ..." (Und ich habe viel zu viel Zeit damit verbracht, um nichts zu posten.)

Hier ist der Code in 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
rvarcher

Hier ist meine Ruby-Implementierung mit dem Test enthalten. Dies würde O(MN) Speicherplatz beanspruchen. Wenn wir ein Echtzeit-Update wünschen (z. B. die Ergebnisse anzeigen möchten, wenn Nullen gefunden werden, anstatt die erste Schleife zum Suchen von Nullen zu warten), können wir einfach eine andere Klassenvariable wie @output erstellen. Wenn wir eine Null finden, aktualisieren wir @output und nicht @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
Eki Eqbal

Obwohl dies angesichts der Einschränkungen nicht möglich ist, besteht der platzsparendste Weg darin, die Matrix in einer überlappenden, abwechselnden Reihen-/Spaltenmethode zu durchlaufen, wodurch ein Muster erzeugt wird, das dem Zick-Zack-Ziegel-Ziegel-Verlegen ähnlich ist:

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

Wenn Sie dies verwenden, würden Sie wie angegeben in jede Zeile/Spalte gehen. Wenn Sie zu einem beliebigen Zeitpunkt eine 0 finden, setzen Sie eine boolesche Variable und gehen diese Zeile/Spalte erneut durch, wobei Sie die Einträge auf 0 setzen.

Dies erfordert keinen zusätzlichen Speicherplatz und verwendet nur eine boolesche Variable. Wenn der "far" Edge auf 0 gesetzt ist, ist dies der ungünstigste Fall, und Sie müssen das gesamte Array zweimal durchlaufen.

0
cdeszaq