20-java - 1차원 배열&이중 반복문 문제들

jin·2022년 5월 26일
0

1. 구구단 출력

for (int i = 2; i <= 9; i++) {
	System.out.printf("===%d단===\n",i);
	for (int j = 1; j <=9; j++) {
		System.out.printf("%d * %d = %d\n", i, j, (i * j) );
	}
}

위의 코드와 같이 작성 가능하다.
i가 한번 돌때 j는 9번 반복하며 이 반복이 끝나면 다시 i값이 증가한다.

2. 로또 문제

[로또]
1~45사이의 랜덤값 6 개를 lotto1 에 저장할려고 한다.
[조건] 중복되는숫자는 없어야한다.




//로또 원리는 공이 섞이다가 나오기때문에 셔플 원리를 이용해야함
Random rnd = new Random();
int[] lotto = new int[6];
int[] lottoNumAll = new int[45];

for (int i = 0; i < lottoNumAll.length; i++) { // 1~45 저장할 배열
	lottoNumAll[i] = i+1;
}

int rNum1 = 0;
int rNum2 = 0;
int temp = 0;
//셔플 반복문 1~45 저장배열 인덱스값 찾아다 섞기
for (int i = 0; i < 50; i++) { // 1~45 저장 배열을 조건식에서 지정한 숫자만큼 반복하며 섞음
	rNum1 = rnd.nextInt(45); 
	rNum2 = rnd.nextInt(45);
	temp = lottoNumAll[rNum1]; // 임시변수에 rNum1에 대한 인덱스를 넣음
	lottoNumAll[rNum1] = lottoNumAll[rNum2]; // rNum1인덱스 자리에 rNum2 인덱스 값을 넣음
	lottoNumAll[rNum2] = temp; // 위에서 rNum1에 대한 인덱스를 넣음, 즉 rNum1과 rNum2 인덱스 위치가 바뀜
	System.out.println(Arrays.toString(lottoNumAll)); // 섞이는거 확인 용도
}
System.out.println();
System.out.println("마지막까지 섞인 전체번호 : " + Arrays.toString(lottoNumAll)+"\n");

for (int i = 0; i < lotto.length; i++) {
	lotto[i] = lottoNumAll[i];
}
System.out.println("lotto 배열에 인덱스 0번부터 순차적으로 값 넣기 : "+Arrays.toString(lotto)+"\n");
/* 오름차순 편하게 하기 - sort 메소드 이용
Arrays.sort(lotto);
System.out.println("lotto 배열 오름차순 : "+Arrays.toString(lotto));
*/
int min = 0;
int index = 0;
// 배열값 오름차순으로 만들기
for (int i = 0; i < lotto.length; i++) {
	min = lotto[i]; //오름차순이니 최소값 구해야함
	index = i;
	
	for (int j = i+1; j < lotto.length; j++) {
		if (min > lotto[j]) {
			min = lotto[j];
			index = j;
		}
	}
	temp = lotto[i];
	lotto[i] = lotto[index]; //두번째 for문에서 구한 min의 인덱스값
	lotto[index] = temp; //min의 인덱스와 현재 인덱스 위치를 바꿈
	System.out.println("lotto 배열 오름차순 정렬 확인용 : " + Arrays.toString(lotto)+"\n");
}
System.out.println("lotto 배열 오름차순 : "+Arrays.toString(lotto));

나는 다른 방식으로 풀었었고 위의 코드는 선생님의 풀이 코드다.
코드를 보다보니 주석 아래 정렬코드와 sort메소드는 무엇이 다른가 궁금해져서 질문했다. sort메소드는 병렬정렬이고 주석 아래 정렬은 직렬정렬이다. 직렬정렬이 효율이 안좋은대신 쉽고 병렬정렬은 효율이 좋은대신 어렵다고...프로그래머스 레벨2 정도라 답해주셨다. 쿨하게 나중에 좀 더 알고리즘에 대해 이해하게 되면 병렬접근도 해보기로 했다다. 알아야 할 것에 우선순위를 정하자...
sort 메소드는 강의에서 다루지 않았는데 저번 포스팅 배열 책정리할때 언급이 돼서 사용해봤다. 덕분에 두 정렬방법 차이도 알았으니 나름 이득이다.

내가 작성한 코드 셔플 방법이 아닌 boolean타입 배열로 중복값 없이 배열에 입력한 코드

import java.util.Arrays;
import java.util.Random;

Random rnd = new Random();
int[] lotto = new int[6];

int rNum = 0;

for (int i = 0; i < lotto.length;) {
	boolean check = false;
	rNum = rnd.nextInt(45)+1;
	for (int j = 0; j < i; j++) { // 배열의 인덱스 마지막 값인 i 만큼 돌려야함
		if (lotto[j]==rNum) {  //한바퀴 돌때마다 배열에 중복값 있는지 체크
				check = true;
				break;
			}
		}
		if (check == false) {
			lotto[i] = rNum;
			i ++;
		}
	}
	System.out.println(Arrays.toString(lotto));
}

단순 생각으로 당연히 난수 6개를 넣는거니까 boolean 타입으로 하면 되겠지 생각했었는데 풀이 코드를 보고 궁금해져서 질문했다. 왜 편하게 중복검사를 해서 넣으면 되는데 굳이 셔플을 해야할까, 이에 대한 답은 실 로또 기계로 추첨할때 1~45 번호를 섞은다음에 뽑기 때문이다. 란 답변을 받았다.
역시... 사람은 눈에 보이거나 알고 있어야 이해가 쉽다...

3. 배열중복삭제

[문제] 값을 입력받고 삭제
[조건] 만약에 같은값이 여러개 있으면 가장첫번째의 값 한개만 삭제 후 b 에 순차적으로 저장

data[] = {5,2,6,8,5,6};

[예] 2 ==> b [] = {5,6,8,5,6,0};
[예] 6 ==> b [] = {5,2,8,5,6,0};


Scanner sc = new Scanner(System.in);
int[] data = { 5, 2, 6, 8 ,5, 6 };
int[] b = new int[6];
System.out.println("기존 배열 : "+Arrays.toString(data));
System.out.print("삭제값 입력 ");
int value = sc.nextInt();
//각각의 배열에 대한 인덱스가 필요함 
int dataIndex = 0;  // data 인덱스
int bIndex = 0; //b 배열 인덱스
boolean check = false;

for (int i = 0; i < data.length; i++) { // 값 유효성 검사
	if (data[i] == value) {
		check = true; 
		dataIndex = i; // 유효성 검사하면서 인덱스를 찾으면 됨
		break;
	}
}
if (check == false) {
	System.out.println("해당값 없음");
}
//		for (int i = 0; i < data.length; i++) { 중복코드 부분
//			if (data[i] == value) {
//				index = i;
//				break;
//			}
//		}

for (int i = 0; i < data.length; i++) {
	if (i != dataIndex) { //data배열 인덱스 위치와 삭제값 인덱스 비교
		b[bIndex] = data[i];
		bIndex += 1;
	}
}
System.out.println("삭제 후 배열 : "+Arrays.toString(b));
sc.close();

그렇다 앞선 포스팅 이중 반복문의 3번의 흔히 하는 중복코드 작성을 또 해버렸다. 반성반성
data 인덱스의 삭제값을 찾은 후 그 외 나머지를 b 배열로 b배열의 인덱스에 순차적으로 접근하면 되는 문제다.

그런데...나는 문제를 대충읽고 data 배열 안에서 삭제처리가 일어나는걸로 오해했다... 아래는 내가 작성한 코드

//문제에서 주어진 변수를 제대로 읽지 않아 망함, 
//문제에서는 배열이 2개 주어짐
Scanner sc = new Scanner(System.in);
int[] data = { 5, 2, 6, 8 ,5, 6 };
int[] b = new int[6];
int index = 0;
int num = 0;

System.out.println("기존 배열 : "+Arrays.toString(data));
System.out.print("삭제값 입력 : ");
num = sc.nextInt();
for (int i = 0; i < data.length; i++) {
	
	if (data[i] == num) {
		index = i;
		break;
	}
}
for (int i = index; i < data.length-1; i++) {
	data[i] = data[i + 1];
}
data[data.length-1] = 0;
System.out.println("삭제 후 배열 : "+Arrays.toString(data));
sc.close();

b[]의 존재를 잊어버린 슬픈 코드..
계속 입력이 아닌 하나만 입력이라 data[data.length-1] = 0;로 삭제처리 해줬다.

4 예매찾기

1) seatList 는 영화관 7자리를 나타낸다.
2) seatList 의 값들은 영화관 예매한 회원번호를 나타낸다.
3) find의 값들은 검색하고자하는 회원번호들이다.
4) find 의 값을 영화관에서 찾아 자리를 출력해주자. 단, 없는번호는 "x" 출력

  • 예) [1] find : 1004 는 없으므로 "x" 출력
  • 예) [2] find : 1003 는 0 , 1
  • 예) [3] find : 1001 는 6
  • 예) [4] find : 1005 는 없으므로 "x" 출력
 int seatList[] = { 1003, 1003, 0, 0, 1002, 0, 1001 };
		
int find[] = { 1004, 1003, 1001, 1005};
System.out.print("[");
for (int i = 0; i < seatList.length; i++) {
	int index = -1;	
	for (int j = 0; j < find.length; j++) {
		if (seatList[i] == find[j]) {
			index = i;
		}
	}
	if (index != -1) {
		System.out.printf(" %d ", index);
	} else {
		System.out.printf(" x ");
	}
//			if (seatList[i] == seatList[index]) {
//				seatList[i] = i;
//			} 
}
System.out.println("]");

또 다시 인덱스를 구해놓고서 또 찾는 코드를 작성했다...

5 예매하기

1) seatList 는 현제 영화관 예매상황 이다.
2) seatIndex 는 예매 할려는 좌석 번호이고
3) userList 는 회원번호이다

4) seatIndex 와 user 를 가지고 예매후 전체 예매상황 출력
5) 좌석이 비어있으면 예매할수있다.
6) 좌석이 이미 예매 되어있으면 2가지조건중 한가지실행
7) [조건 1] 이미 예매되어있으나, 회원번호가 같으면 예매취소 0으로 변경
8) [조건 2) 이미 예매되어있고 , 회원번호가 다르면 "x" 출력

  • 예) 1 , 1003 ==> 예매 되어있으나, 1003번이 예매했으므로 예매 취소된다
    ==> seatList[] = {1003,0,0,0,1002,0,1001};

  • 예) 1 , 1002 ==> 위에서 예매취소했으므로 예매 가능
    ==> seatList[] = {1003,1002,0,0,1002,0,1001};

  • 예) 4 , 1005 ==> 예매 되어있고, 회원번호도 다르다 ==> "x"


int seatList[] = { 1003, 1003, 0, 0, 1002, 0, 1001};		
int seatIndex[] = { 1, 1, 4 };
int userList [] = { 1003, 1002, 1005};

for (int i = 0; i < userList.length; i++) {
	int index = seatIndex[i];
	if (seatList[index] == 0) {
		System.out.print(userList[i] + " : ");
		seatList[index] = userList[i];
		System.out.println(Arrays.toString(seatList));
	} else if (seatList[index] == userList[i]) {
		System.out.print(userList[i] + " : ");
		seatList[seatIndex[i]] = 0;
		System.out.println(Arrays.toString(seatList));
	} else if (seatList[index] != 0 && seatList[index] != userList[i]) {
		System.out.println("x");
	}
}

seatIndex[i]가 index가 되므로 해당 값을 변수로 생성해주면 seatList[seatIndex[i]] 보다 보기 좋다.

6 왼쪽 오른쪽 정렬

[왼쪽오른쪽]
아래 번호를 입력받고 각방향 으로 0 이아닌숫자를 모으시요.
1)left 2)right
예) 1) left ==> arr = {2,3,4,5,0,0,0,0,0};
예) 1) right ==> arr = {0,0,0,0,0,2,3,4,5};

int arr1[] = { 0, 2, 0, 3, 4, 0, 0, 5, 0 };
		
// 왼정렬 ===> 뭐가 필요할까 ===> 왼쪽 정렬할 인덱스, 전체인덱스는 접근은 0부터니 for문 i변수로
int leftIndex = 0;
int temp = 0;
for (int i = 0; i < arr1.length; i++) {
	if (arr1[i] != 0) { // 0이 아닐때마다 왼쪽인덱스+1
		temp = arr1[i];
		arr1[i] = arr1[leftIndex];
		arr1[leftIndex] = temp;
		leftIndex += 1;
	}
}
System.out.println(Arrays.toString(arr1));

int arr2[] = { 0, 2, 0, 3, 4, 0, 0, 5, 0 };
// 오른정렬 ===> 뭐가 필요할까 ===> 오른쪽 정렬할 인덱스 / 순차접근 인덱스 끝부터 배열크기-1
int index = arr2.length-1;
int rightIndex  = index;
for (int i = 0; i < arr2.length; i++) {
	if (arr2[index] != 0 ) {
		temp = arr2[index];
		arr2[index] = arr2[rightIndex];
		arr2[rightIndex] = temp;
		rightIndex -= 1;
	}
	index -= 1;
}
System.out.println(Arrays.toString(arr2));

임시변수에 a값을 옮겨담고 b에 a값을 넣고 b에 임시변수에 저장한 a값을 담는 과정을 이해했다고 생각했는데 배열로 들어오니 혼돈파괴망각이 되었다... 공책에 각 i번째당 과정을 쭉 쓰고 콘솔창 각 과정과 비교해보니 이해함에 눈으로 보는 것 보다 훨씬 나았다.



오른쪽 정렬 경우

인덱스 끝부터 접근해야함
for문에서 --로 변수값을 감소하며 접근하는건 좋지 않음
차라리 변수를 더 사용하기

감소하며 조건판별할 인덱스 = arr.length-1
오른쪽부터 자리 채울 인덱스 = 감소하며 조건판별할 인덱스
0만나면 한칸씩 자리바꿈, temp가 필요함

조건판별할 인덱스는 반복문이 돌때마다 감소
자리 위치 인덱스는 조건에 해당할때마다 감소

왼쪽 정렬

증가하며 접근하니 i를 전체인덱스
왼쪽 인덱스 따로 두기
임시저장할 변수(temp)
0이 아닐때 왼쪽인덱스 +1

오른쪽 정렬할때 굳이 배열크기-1에서 접근할 필요없이 i 값을 감소하며 접근하면 되지 않나 라는 질문을 선생님께 했는데 그건 작성자만 알아볼 수 있다고... 반복문에서는 증가하며 접근하고 그 안에서 인덱스값을 따로 빼주는게 좋다 들었다.

7. 정렬

[정렬]
1. 인덱스 0번이 나머지를 검사한다.
2. 제일 큰 값을 찾아 교환한다.
3. 인덱스 1증가한다.
4. [1~3]을 끝까지 반복한다.
예)
10, 50, 30, 40, 80, 19 ==> 80을 찾아내고 교환한다.
80, 50, 30, 40, 10, 19 ==> 50은 나머지중 이미 제일크다.
80, 50, 30, 40, 10, 19 ==> 40을 찾아내고 교환한다.
80, 50, 40, 30, 10, 19 ==> 30은 나머지중 이미 제일크다.
80, 50, 40, 30, 10, 19 ==> 19을 찾아내고 교환한다.
80, 50, 40, 30, 19, 10


int[] score = { 10, 50, 30, 40, 80, 19 };
//문제 이중for문
for (int i = 0; i < score.length; i++) {
	int max = score[i]; // i번째에 있는 값이 큰지 비교해야함
	int index = i; // 증가하면서 비교할 위치
	System.out.println((i+1) +"번쨰");
	for(int j = i+1; j < score.length; j++) { // 늘 i 다음 위치랑 비교해야함 i+j가 6보다 크면 안돌아서 에러x
		if (score[j] > max) { // i에서 j번째 값이 max보다 클경우
			max = score[j]; // max에 j값
			index = j; // index에 j번째 인덱스 기억함 ===> 두번째 for문 끝나고 바꿀 위치 저장
		}
	}
	int temp = score[i]; // 바꾸기 위해서 기존 i번째 값 기억
	score[i] = score[index]; //두번째 for문에서 기억안 인덱스위치에 i번 넣기 ===> 정렬순서
	score[index] = temp; // 인덱스 위치에는 작은값으로 교체
}
System.out.println();
System.out.println(Arrays.toString(score));

왼오정렬과 인덱스 위치바꾸는게 머릿속에서 뒤섞이다보니 주석을 달며 다시 한번 이해하는 과정을 가졌다.

덤. 인덱스를 어느정도 이해했다 생각했는데 하다보니 머릿속이 뒤죽박죽이다. 개념이 정립되는 느낌을 받음.

0개의 댓글