Domanda

Data una matrice NxN con 0s e 1s. Imposta ogni riga che contiene un 0 su tutti i 0 e imposta ogni colonna che contiene un 0 su tutti i 0 s.

Ad esempio

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

risulta 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

Un tecnico Microsoft mi ha detto che esiste una soluzione che non richiede memoria aggiuntiva, solo due variabili booleane e un passaggio, quindi sto cercando quella risposta.

A proposito, immagina che sia una matrice di bit, quindi solo 1 e 0 possono essere nella matrice.

È stato utile?

Soluzione

Ok, quindi sono stanco perché sono le 3 del mattino, ma ho un primo tentativo sul posto con esattamente 2 passaggi su ciascun numero nella matrice, quindi in O (NxN) ed è lineare nella dimensione della matrice.

Uso la prima colonna e la prima riga come marker per sapere dove sono le righe / i col solo 1. Quindi, ci sono 2 variabili l e c da ricordare se anche la prima riga / colonna sono tutte 1. Quindi il primo passaggio imposta i marcatori e reimposta il resto su 0

Il secondo passaggio imposta 1 nei punti in cui le righe e i punti sono contrassegnati come 1 e reimposta la prima riga / i a seconda di l e c.

Dubito fortemente che possa essere fatto in 1 passaggio poiché i quadrati all'inizio dipendono dai quadrati alla fine. Forse il mio secondo passaggio può essere reso più efficiente ...

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)

Altri suggerimenti

Questo non può essere fatto in un passaggio poiché un singolo bit ha effetto sui bit prima e dopo di esso in qualsiasi ordine. IOW Qualunque sia l'ordine in cui attraversi l'array, potresti in seguito imbatterti in uno 0, il che significa che devi tornare indietro e cambiare un precedente 1 in uno 0.

Aggiorna

Le persone sembrano pensare che limitando N ad un valore fisso (diciamo 8) è possibile risolvere questo passaggio. Bene questo è a) manca il punto eb) non la domanda originale. Non pubblicherei una domanda sull'ordinamento e non mi aspetterei una risposta che è iniziata "supponendo che tu voglia solo ordinare 8 cose ..."

Detto questo, è un approccio ragionevole se si sa che N è in realtà limitato a 8. La mia risposta sopra risponde alla domanda originale che non ha tale ritrattazione.

Quindi la mia idea è quella di utilizzare i valori nell'ultima riga / colonna come flag per indicare se tutti i valori nella colonna / riga corrispondente sono 1s.

Utilizzo di una Scansione a zig zag attraverso l'intera matrice EXCEPT l'ultima riga / colonna. Ad ogni elemento, si imposta il valore nell'ultima riga / colonna sull'AND logico di se stesso con il valore nell'elemento corrente. In altre parole, se si preme uno 0, l'ultima riga / colonna verrà impostata su 0. Se si ottiene un 1, il valore nell'ultima riga / colonna sarà 1 solo se era già 1. In ogni caso, imposta l'elemento corrente su 0.

Al termine, la riga / colonna finale dovrebbe avere 1 se la colonna / riga corrispondente è stata riempita con 1s.

Esegui una scansione lineare attraverso l'ultima riga e colonna e cerca 1 secondo. Imposta 1s negli elementi corrispondenti nel corpo della matrice in cui la riga e la colonna finali sono entrambe 1s.

Codificare sarà complicato evitare errori off-by-one, ecc., ma dovrebbe funzionare in un unico passaggio.

Ho una soluzione qui, funziona in un unico passaggio e fa tutto l'elaborazione "in atto" senza memoria aggiuntiva (salvo per aumentare lo stack).

Usa la ricorsione per ritardare la scrittura di zeri che, naturalmente, distruggerebbero la matrice per le altre righe e caratteri:

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

Non penso sia fattibile. Quando sei sul primo quadrato e il suo valore è 1, non hai modo di sapere quali sono i valori degli altri quadrati nella stessa riga e colonna. Quindi devi controllare quelli e se c'è uno zero, torna al primo quadrato e cambia il suo valore in zero. Ti consiglio di farlo in due passaggi: il primo passaggio raccoglie informazioni su quali righe e colonne devono essere azzerate (le informazioni sono memorizzate in un array, quindi stiamo usando un po 'di memoria aggiuntiva). Il secondo passaggio modifica i valori. So che non è la soluzione che stai cercando, ma penso che sia pratica. I vincoli forniti dall'utente rendono il problema irrisolvibile.

Posso farlo con due variabili intere e due passaggi (fino a 32 righe e colonne ...)

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

il problema può essere risolto in un solo passaggio

salvataggio della matrice in un array 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 .

ora stampa tutti i valori come 0 per i valori di iej salvati in a e b il resto dei valori sono 1 cioè (3,3) (3,4) (5,3) e (5,4)

Un'altra soluzione che richiede due passaggi è quella di accumulare AND orizzontalmente e verticalmente:

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    

Pensavo di poter progettare un simile algoritmo usando bit di parità , Codici di hamming o programmazione dinamica , probabilmente usando quei due booleani come numero a 2 bit, ma non ho ancora avuto successo.

Potete ricontrollare la dichiarazione del problema con il vostro ingegnere e farcelo sapere? Se lì è davvero una soluzione, voglio continuare a risolvere il problema.

Mantieni una singola variabile per tenere traccia di quali sono tutte le righe ANDed insieme.

Se una riga è -1 (tutti 1), quindi fare della riga successiva un riferimento a quella variabile

Se una riga è tutt'altro che, è uno 0. Puoi fare tutto in un passaggio. Pseudo-codice:

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

Dovrebbe farlo, in un unico passaggio, ma qui si presume che N sia abbastanza piccolo da consentire alla CPU di eseguire l'aritmetica su una singola riga, altrimenti sarà necessario scorrere su ogni riga per determinare se è tutto 1s o no, credo. Ma dato che stai chiedendo di algos e di non limitare il mio hardware, vorrei solo iniziare la mia risposta con " Costruire una CPU che supporti l'aritmetica N-bit ... "

Ecco un esempio di come si può fare in C. Nota: sostengo che i valori e arr presi insieme rappresentano l'array, e p e numproduct sono il mio iteratore e le variabili di prodotto AND utilizzate per implementare il problema. (Avrei potuto fare un giro su arr con aritmetica del puntatore per convalidare il mio lavoro, ma una volta era abbastanza!)

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

Questo produce 0, 0, 6, 0, 6, che è il risultato per gli input dati.

O in PHP, se la gente pensa che i miei giochi stack in C stiano tradendo (ti suggerisco di no, perché dovrei essere in grado di memorizzare la matrice come preferisco):

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

Mi manca qualcosa?

Bella sfida. Questa soluzione utilizza solo due booleani creati nello stack, ma i booleani vengono creati più volte nello stack poiché la funzione è ricorsiva.

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

Questo scansiona in uno schema come:

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

e così via

E quindi cambiando i valori in questo modello al ritorno su ciascuna delle funzioni di scansione. (Bottom up):

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

e così via

Va bene questa è una soluzione che

  • utilizza solo un valore extra lungo per l'archiviazione di lavoro.
  • non utilizza alcuna ricorsione.
  • un passaggio di solo N, nemmeno N * N.
  • funzionerà con altri valori di N ma avrà bisogno di nuovi #define.
#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;
    }

In realtà. Se si desidera solo eseguire l'algoritmo e stampare i risultati (ovvero non ripristinarli, è possibile farlo facilmente in un unico passaggio. Il problema si presenta quando si tenta di modificare l'array mentre si esegue l'algoritmo.

Ecco la mia soluzione implica solo ANDing i valori di righe / colonne per un elemento di givein (i, j) e stamparlo.

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

Ho provato a risolvere questo problema in C #.

Ho usato due variabili di loop (iej) oltre alla matrice effettiva n che rappresentano la sua dimensione

La logica che ho provato è:

  1. Calcola AND per righe e colonne coinvolti in ciascun quadrato concentrico della matrice
  2. Conservalo nelle sue celle angolari (le ho archiviate in senso antiorario)
  3. Due variabili bool sono utilizzate per conservare i valori di due angoli durante la valutazione di un quadrato particolare.
  4. Questo processo terminerebbe quando il circuito esterno (i) è a metà strada.
  5. Valuta i risultati di altre celle in base alle celle d'angolo (per il resto di i). Salta le celle d'angolo durante questo processo.
  6. Quando raggiungo n, tutte le celle avrebbero il suo risultato tranne le celle d'angolo.
  7. Aggiorna le celle d'angolo. Questa è un'iterazione extra per la lunghezza di n / 2 diversa dal vincolo single pass menzionato nel problema.

Codice:

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

Sebbene impossibile dato i vincoli, il modo più efficiente in termini di spazio per farlo è attraversare la matrice in modo sovrapposto e alternato riga / colonna, che renderebbe un modello simile alla posa di mattoni a zig-zag:

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

Usando questo, andresti in ogni riga / colonna, come indicato, e se incontri uno 0 in qualsiasi momento, imposta una variabile booleana e ricomincia da capo quella riga / colonna, impostando le voci su 0 mentre procedi .

Ciò non richiederà memoria aggiuntiva e utilizzerà solo una variabile booleana. Sfortunatamente, se il "lontano" edge è impostato su 0, questo è il caso peggiore e percorri l'intero array due volte.

crea una matrice di risultati e imposta tutti i valori su 1. passare attraverso la matrice di dati non appena viene rilevato uno 0, impostare la colonna della riga della matrice dei risultati su 0

Alla fine del primo passaggio, la matrice dei risultati avrà la risposta corretta.

Sembra piuttosto semplice. C'è un trucco che mi manca? Non puoi utilizzare un set di risultati?

EDIT:

Sembra una funzione F #, ma questo è un po 'barare poiché, anche se stai facendo un singolo passaggio, la funzione può essere ricorsiva.

Sembra che l'intervistatore stia cercando di capire se conosci la programmazione funzionale.

Bene, ho trovato una soluzione single-pass, sul posto (non ricorsiva) usando 4 bool e 2 contatori a loop. Non sono riuscito a ridurlo a 2 bool e 2 ints, ma non sarei sorpreso se fosse possibile. Fa circa 3 letture e 3 scritture di ogni cella, e dovrebbe essere O (N ^ 2) cioè. lineare nella dimensione dell'array.

Mi ci sono volute un paio d'ore per risolvere questo problema - non avrei voluto inventarmelo sotto la pressione di un'intervista! Se ho fatto un booboo sono troppo stanco per individuarlo ...

Uhm ... sto scegliendo di definire " single-pass " come fare uno sweep attraverso la matrice, piuttosto che toccare ogni valore una volta! : -)

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

Spero che ti piaccia la mia soluzione c # a 1 passaggio

puoi recuperare un elemento con O (1) e solo bisogno lo spazio di una riga e una colonna della matrice

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

1 passaggio, 2 booleani. Devo solo supporre che gli indici interi nelle iterazioni non contino.

Questa non è una soluzione completa ma non riesco a superare questo punto.

Se solo potessi determinare se uno 0 è uno 0 originale o uno convertito in uno 0, non dovrei usare -1 e questo funzionerebbe.

La mia uscita è così:

-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

L'originalità del mio approccio sta usando la prima metà dell'esame di una riga o colonna per determinare se contiene uno 0 e l'ultima metà per impostare i valori - questo viene fatto guardando x e larghezza-x e poi y e height-y in ogni iterazione. In base ai risultati della prima metà dell'iterazione, se viene trovato uno 0 nella riga o nella colonna, utilizzo l'ultima metà dell'iterazione per modificare gli 1 in -1.

Ho appena realizzato che questo potrebbe essere fatto con solo 1 booleano che lascia da 1 a ...?

Sto pubblicando questo nella speranza che qualcuno possa dire, " Ah, fallo e basta ... " (E ho speso troppo tempo per non pubblicare.)

Ecco il codice 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

Nessuno sta usando i moduli binari? poiché è solo 1 e 0. Possiamo usare i vettori binari.

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

Ecco il 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)

E l'output:

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

Puoi fare qualcosa del genere per usare un passaggio ma una matrice di input e output:

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

dove col (xy) sono i bit nella colonna che contengono il punto xy ; row (xy) sono i bit nella riga che contengono il punto xy . n è la dimensione della matrice.

Quindi basta passare sull'input. Forse espandibile per essere più efficiente nello spazio?

Una scansione a matrice, due booleani, nessuna ricorsione.

Come evitare il secondo passaggio? Il secondo passaggio è necessario per cancellare le righe o le colonne quando lo zero appare alla loro fine.

Tuttavia, questo problema può essere risolto, perché quando eseguiamo la scansione della riga #i conosciamo già lo stato della riga # i-1. Pertanto, mentre eseguiamo la scansione della riga #i, possiamo cancellare contemporaneamente la riga # i-1 se necessario.

La stessa soluzione funziona per le colonne, ma è necessario eseguire la scansione di righe e colonne contemporaneamente mentre i dati non vengono modificati dalla successiva iterazione.

Sono necessari due booleani per memorizzare lo stato della prima riga e della prima colonna, poiché i loro valori verranno modificati durante l'esecuzione della parte principale dell'algoritmo.

Per evitare di aggiungere altri booleani, stiamo memorizzando il "cancella" flag per le righe e le colonne nella prima riga e colonna della matrice.

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

sembra che i seguenti lavori senza requisiti di spazio aggiuntivi:

prima nota che moltiplicando gli elementi della riga per gli elementi della linea in cui si trova un elemento, si ottiene il valore desiderato.

Per non utilizzare alcuno spazio aggiuntivo (non creare una nuova matrice e riempirla ma applicare direttamente le modifiche alla matrice), inizia in alto a sinistra della matrice ed esegui il calcolo per qualsiasi matrice ixi (che " inizia " ; at (0,0)) prima di considerare qualsiasi elemento con qualsiasi indice > i.

spero che funzioni (havent testet)

Questo è TESTATO per N diverso in C ++ ed è:
UN PASSO , DUE BOOLS , NESSUNA RICURSIONE , NESSUNA MEMORIA EXTRA , ATTESA PER ARBITRARMENTE GRANDI N
(Finora nessuna delle soluzioni qui fa TUTTE queste.)

Più specificamente, sto divertendo i contatori a due loop vanno bene. Ho due const non firmati, che esistono solo anziché essere calcolati ogni volta per leggibilità. L'intervallo del loop esterno è [0, N] e l'intervallo del loop interno è [1, n - 1]. L'istruzione switch è nel ciclo per lo più esiste per mostrare molto chiaramente che in realtà è solo un passaggio.

Strategia algoritmo:

Il primo trucco è per noi una riga e una colonna dalla matrice stessa per accumulare il contenuto della matrice, questa memoria diventa disponibile scaricando tutto ciò che dobbiamo veramente sapere dalla prima riga e colonna in due booleani. Il secondo trucco è ottenere due passaggi da uno, usando la simmetria della sotto-matrice e dei suoi indici.

Sinossi dell'algoritmo:

  • Scansiona la prima riga e archivia se sono tutti in un valore booleano, fai lo stesso per la prima colonna che memorizza il risultato in un secondo valore booleano.
  • Per la matrice secondaria esclusa la prima riga e la prima colonna: scorrere attraverso, da sinistra a destra, dall'alto verso il basso, come si leggerebbe un paragrafo. Dopo aver visitato ciascun elemento, visita anche l'elemento corrispondente che verrebbe visitato se visitassi la matrice secondaria al contrario. Per ogni elemento visitato AND il suo valore nel punto in cui la sua riga attraversa la prima colonna e anche il valore AND in cui la sua colonna attraversa la prima riga.
  • Una volta raggiunto il centro della matrice secondaria, continua a visitare i due elementi contemporaneamente come sopra. Tuttavia ora imposta il valore degli elementi visitati su AND di dove la sua riga attraversa la prima colonna e di dove la sua colonna attraversa la prima riga. Dopodiché, la matrice secondaria è completa.
  • Utilizzare le due variabili booleane calcolate durante l'accattonaggio per impostare la prima riga e la prima colonna sui valori corretti.

Implementazione C ++ templatizzata:

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

Ok, mi rendo conto che non è proprio una corrispondenza, ma l'ho preso in un passaggio usando un bool e un byte invece di due bool ... chiudi. Inoltre, non garantisco l'efficienza, ma questi tipi di domande spesso richiedono soluzioni non ottimali.

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

Puoi farlo in un solo passaggio - se non conti l'accesso alla matrice in ordine di accesso casuale, il che elimina in primo luogo i vantaggi del passaggio singolo (coerenza cache / larghezza di banda di memoria ).

[modifica: eliminata la soluzione semplice ma errata]

Dovresti ottenere prestazioni migliori rispetto a qualsiasi metodo a passaggio singolo eseguendolo in due passaggi: uno per accumulare informazioni su riga / colonna e uno per applicarlo. L'array (nell'ordine delle righe principali) è accessibile in modo coerente; per array che superano le dimensioni della cache (ma le cui righe possono rientrare nella cache), i dati devono essere letti dalla memoria due volte e archiviati una volta:

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

La soluzione più semplice che mi viene in mente è incollata di seguito. La logica è registrare quale riga e colonna impostare zero durante l'iterazione.

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

Ecco la mia implementazione di Ruby con il test incluso, questo occuperebbe spazio O (MN). Se vogliamo un aggiornamento in tempo reale (ad esempio per mostrare i risultati quando troviamo gli zeri piuttosto che attendere il primo ciclo di ricerca degli zeri) possiamo semplicemente creare un'altra variabile di classe come @output e ogni volta che troviamo uno zero aggiorniamo @output e non @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

Il codice seguente crea una matrice di dimensioni m, n. Decidi innanzitutto le dimensioni della matrice. Volevo riempire la matrice [m] [n] in modo casuale con numeri tra 0..10. Quindi crea un'altra matrice delle stesse dimensioni e riempila con -1s (matrice finale). Quindi scorrere la matrice iniziale per vedere se si preme 0. Quando si preme sulla posizione (x, y), andare alla matrice finale e riempire la riga x con 0s e la colonna y con 0s. Alla fine leggi attraverso la matrice finale, se il valore è -1 (valore originale) copia il valore nella stessa posizione della matrice iniziale in final.

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

ecco la mia soluzione. Come puoi vedere dal codice, data una matrice M * N, imposta l'intera riga su zero una volta ispezionato uno zero in quella riga. La complessità temporale della mia soluzione è O (M * N). Sto condividendo l'intera classe che ha un array popolato statico per i test e un metodo di array display per vedere il risultato nella console.

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

}

}

One Pass: ho attraversato l'input solo una volta ma ho usato un nuovo array e solo due variabili booleane aggiuntive.

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

    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top