22-java - 1차원 배열 복합문제들

jin·2022년 6월 3일
0

1. 가로세로 합

[문제1] array 배열을 위 와같이 사각형 모양으로 출력 하고
각줄의 가로 합을 garo1[] 에 차례대로 저장

[문제2] array 배열을 위 와같이 사각형 모양으로 출력 하고
각줄의 세로 합을 sero1[] 에 차례대로 저장

int array[] = {
		2, 4, 6,
		8, 1, 5,
		9, 7, 3
};

int garo[] = { 0, 0, 0 }; // {2+4+6 , 8+1+5 , 9+7+3}
int sero[] = { 0, 0, 0} ; // {2+8+9 , 4+1+7 , 6+5+3}
int garoIndex = 0;
int seroIndex = 0;
for (int i = 0; i < array.length; i++) {
	// 가로 0,3,6 세로 0,1,2 
	garo[garoIndex] += array[i];
	sero[seroIndex] += array[i];
	seroIndex++; // 세로인덱스 1칸씩 증가하며 더함 ==> 012 ==> 345 => 567
	if( i%3 == 2) { // 세번째
		garoIndex ++; // 가로는 인덱스+1
		seroIndex = 0; // 세로는 인덱스 = 0 ===> 다음에 다시 0번째부터 더할 수 있도록
	}
}
System.out.println(Arrays.toString(garo));
System.out.println(Arrays.toString(sero));

위의 코드는 답안코드로 나는 처음에 다르게 작성했었다.

int array[] = {
		2, 4, 6,
		8, 1, 5,
		9, 7, 3
};

int garo[] = { 0, 0, 0 }; // {2+4+6 , 8+1+5 , 9+7+3}
int index = 0;
int sum = 0;
for (int i = 0; i < array.length; i+=3) {
	sum = ( array[i] + array[i+1] + array[i+2] );
	garo[index] = sum;
	index += 1;
}
System.out.println(Arrays.toString(garo));

int sero[] = { 0, 0, 0} ; // {2+8+9 , 4+1+7 , 6+5+3}
for (int i = 0; i < sero.length; i++) {
	sum = ( array[i] + array[i+3] + array[i+6] );
	sero[i] = sum;
}
System.out.println(Arrays.toString(sero));

이렇게 i가 3씩 증가하는 형태로 깡계산을 했다.
정답은 나오나 알고리즘적으로 접근하지는 못한 사례.

2. 개수찾기 문제

가장많이 들어있는 숫자개수와
가장 적게 들어있는 숫자의 개수의 합을 구하시요.
100 : 1개
3 : 5개
답 : 6

int[] arr = { 1, 2, 3, 3, 100, 1, 3, 3, 2, 3, 2 };
//[1] 새로운 배열을 만들어서 중첩되지않는 값만 저장한다.
// ex) temp = {1,2,3,100}
int[] sample = new int[arr.length]; // arr 배열의 중복값들을 모르니 모든 경우의 수를 생각해 arr배열 크기만큼 만듦
int[] count = new int[arr.length]; //
int sampleCount = 0;
for (int i = 0; i < arr.length; i++) {
	boolean check = false;
//			for (int j = 0; j < sample.length; j++) { sample 배열 크기만큼 검사하면 효율이 안좋음
	for (int j = 0; j < sampleCount; j++) { //중복값 아닐때 증가한만큼만 돌리면 반복이 덜 돌음 
		if(sample[j] == arr[i]) {
			check = true;
			break;
		}
	}
	if (check == false) { // 이부분은 중복값 찾기랑 같음
		sample[sampleCount] = arr[i];
		sampleCount ++;
	}
}
System.out.println(Arrays.toString(sample));
System.out.println(sampleCount);

for (int i = 0; i < arr.length; i++) {//중복갯수 저장하는 반복문
	for(int j = 0; j < sampleCount; j++) { // 위와 동일한 이유로 조건 부여
		if(arr[i] == sample[j]) { // 중복배열과 샘플배열이 같으면 증가
			count[j]++;
		}
	}
}
System.out.println(Arrays.toString(count));
int maxIndex = 0;
int minIndex = 0;
int max = 0;
int min = 100;
for (int i = 0; i < sampleCount; i++) {
	if (max < count[i]) {
		max = count[i];
		maxIndex = i;
	}
	if (min > count[i]) {
		min = count[i];
		minIndex = i;
	}
}
System.out.printf("%d : %d개\n" , sample[minIndex], min);
System.out.printf("%d : %d개\n" , sample[maxIndex], max);
System.out.println("답 : " + (max+min) );

처음 접했을때 어떻게 풀어야할지 감조차 오지 않아 헤맸던 문제. sampleCount변수로 sample 전체를 반복하는 것 보다 효율적으로 접근할 수 있음을 알았다.
답안코드 보고 작성하고, 주석달고 몇번 다시 풀고 해서 어느정도 이해돼 다른 응용문제도 무사히 풀 수 있게 됐다.
앞으로 두세번은 더 풀어봐야 어느정도에서 완전히로 바뀌게 될듯싶다.

3. 기념일

철수와 영희는 3월 3일에 만났다.
철수는 영희와 100일 기념일에 축하파티를 할려고한다.
만난지 100일뒤는 몇월몇일인가?
단 윤년은 계산하지않는다.

int monthList[] =
	{31, 28, 31, 30, 
	 31, 30, 31, 31, 
	 30, 31, 30, 31};

int day = 3;
int month = 3;
// 1. 만난 날짜를 일수로 바꿈
for (int i = 0; i < month-1; i++) {
	day += monthList[i];
}
System.out.println(day);
// 2. 바꾼 일수에 디데이를 더함
day = day + 100;
System.out.println(day);
int day2 = 0;
// 3. day를 monthList i번째 만큼 빼다가 0 이하로 가면 해당 월
for (int i = 0; i < monthList.length; i++) {
	day2 = day;
	day -= monthList[i];
	if (day <= 0) {
		System.out.println( (i+1) +"월");
		System.out.println(day2 + "일");
		break;
	}
}

어떻게 접근해야될지 몰랐던 문제2. 먼저 만난 날짜를 일수로 바꿔준 후 디데이를 더한 후 달에 해당하는 만큼 총 일수를 차감하면서 반복하면 답이 구해졌던 문제이다.

4. 배열비교1

[문제] array 배열 안의 값들중에서 b배열의 값이 있으면
b와 array의 각각 겹치는값을 0으로 변경

[예]
array[] = {0,0,30,40};
b[] = {0,3,0,50};

int arr[] = { 10, 20, 30, 40 };
int b[] = { 10, 3, 20, 50 };

for (int i = 0; i < arr.length; i++) {
	for (int j = 0; j < b.length; j++) {
		if (arr[i] == b[j]) {
			arr[i] = 0;
			b[j] = 0;
		}
	}
}
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(b));

두번째 반복문에서 arr배열의 i번째와 b배열의 j번째가 같은 값, 즉 중복되는 값일때 0을 넣어주면 되는 간단한 문제.

5. 배열비교2

arr1 배열과 input 배열을 비교한다.
서로같은 값이 있는지 체크한다.
같은값을 찾으면 arr1의 값이 있는 인덱스를 b에 저장한다.
input 숫자가 arr1 에 없으면 인덱스 대신 -1 저장한다.
[예] input[] ==> { 30, 40, 1, 10, 2 }
[예] arr1[] = {10, 20, 30, 40};

   1) 30 은 arr1[2] 이므로 2저장 
   2) 40 은 arr1[3] 이므로 3저장
   3) 1 은 arr1에 없으므로 -1 저장
   4) 10 은 arr1[0] 이므로 0 저장
   5) 2는 arr1에 없으므로 -1  저장 	
   

[예] b = { 2, 3, -1, 0, -1}

int input[] = { 30, 40, 1, 10, 2 };
int arr[] = { 10, 20, 30, 40 };

int b[] = { -1, -1, -1, -1, -1 };
// 전체검사
for (int i = 0; i < input.length; i++) {
	for (int j = 0; j < arr.length; j++) {
		if (input[i] == arr[j]) {
			b[i] = j;
		}
	}
}
System.out.println(Arrays.toString(b));

기준이 되는 배열을 잡고 반복문으로 전체 값을 확인하여 중복되는 값들의 인덱스를 넣어주면 되는 비교적 간단한 문제2

6. 숫자 야구 게임

  1. me에 1~9 사이의 숫자 3개를 저장
    (단, 중복되는 숫자는 저장 불가)
    예) 1,1,1
  2. com과 me를 비교해 정답을 맞출 때까지 반복
  3. 숫자와 자리가 같으면 strike += 1
    숫자만 같고 자리가 틀리면 ball += 1
    예)
    정답 : 1 7 3
    3 1 5 : 2b
    1 5 6 : 1s
    ...
Random rnd = new Random();
int[] com = { 1, 7, 3 };
int[] me = new int[3];

int strike = 0;
int ball = 0;

while (true) {
	if (strike >=3) {
		System.out.println("쓰리 스트라이크");
		System.out.println("종료");
		break;
	}
	boolean[] check = new boolean[9]; // 반복 돌때마다 초기화
	for (int i = 0; i < me.length; ) {
		int rNum = rnd.nextInt(9)+1;
		int index = rNum-1;
		if (check[index] == false) {
			me[i] = rNum;
			check[index] = true;
			i++;
		}
	}
	// 전체검사 ===> 숫자와 자리가 같으면 	strike += 1 / 숫자만 같고 자리가 틀리면 	ball += 1
	for (int i = 0; i < com.length; i++) {
		if ( com[i] == me[i] ) {
			strike ++;
			continue;
		}
		for (int j = 0; j < me.length; j++) {
			if (com[i] == me[j] ) {
				ball ++;
				continue;
			}
		}
	}
	System.out.println("com : "+Arrays.toString(com));
	System.out.printf("me : "+Arrays.toString(me));
	System.out.printf(" / strike : %d, ball : %d\n", strike, ball);
	System.out.println("---------------------------------------------");
}

그동안의 노력이 헛되지 않았는지 생각보다 쉽게 풀린 문제. 그런데 문제 내에서는 쓰리 스트라이크로 게임이 끝나는지 아닌지 몰랐는데 코드 해설 강의를 보니 '게임'인 만큼 끝나는 조건이 있었다.

7. 압축문제

arr1 = {1,1,1,3,3,3,3,2,2,3,3,3,4,5};
arr1의 중에서 연속으로 중복되는 숫자는 제외하고 숫자 1개씩만 압축해서
b에 저장하려고 한다.
[예] b[] = {1,3,2,3,4,5}

/*
 	1) 연속되는 숫자인지 검사 해야하므로 b[0] 에 arr의 첫번째 값을 저장한다.
 	2) arr[1]부터 순차적으로 b[0]와 비교해서 다른 값이 나올때마다 index를 증가시키고 저장한다.
 */
int arr[] = { 1, 1, 1, 3, 3, 3, 3, 2, 2, 3, 3, 3, 4, 5 };
int b[] = new int[arr.length];
int index = 0;
int count = 0;
b[index] = arr[0];
for (int i = 1; i < arr.length; i++) {
	if (b[index] != arr[i]) {
		index ++;
		b[index] = arr[i];
		
	}
	count++;
}
System.out.println(Arrays.toString(b));
System.out.println(count);

의외로 헤맸던 문제. 접근이 잘못됐었다.
압축, 즉 연속된 숫자 다음에 다른 수가 나오면 저장을 해야하는데 그냥 중복되지 않는 수를 싹 다 저장하는 이전과 비슷한 코드를 작성했었다. 아무리 해봐도 뭔가 이상해서 보니 접근이 틀려서 값이 안나오는 슬픈 상황...
이 슬픈 상황을 뒤로 하고 b배열의 첫번째 인덱스에 arr의 첫번째 인덱스 값을 넣고 그 후 값들이랑 중복되는지 비교하면 되는 문제였다.

8. 중복제거 문제

[문제] arr 배열 안의 값들중에서 b배열의 값이 있으면
b와 arr의 각각 겹치는값을 0으로 변경
[조건] 겹치는 값이 여러개 있으면 전부 0으로 변경
예) arr[] = {0,0,30,40,0};
예) b[] = {0,3,0,0,0,50};

int arr1[] = { 10, 20, 30, 40, 20 };
int b[] = { 10, 3, 20, 10, 20, 50 };
int count = 0;
for(int i = 0; i < arr1.length; i++) {
	int value = arr1[i];
	for(int j = 0; j < b.length; j++) {
		if(value == b[j]) {
			b[j] = 0;
			for(int k = i; k < arr1.length; k++) {
				if(value == arr1[k]) {
					arr1[k] = 0;
				}
				count ++;
			}
		}			
	}					
}	
System.out.println(count);

위의 코드는 답안코드로... 무려 삼중 for문이다...
삼중 for문 현기증을 살짝 느껴 다른 방법으로 시도해봤다.

시도해봤다가 망한 코드

~~

//arr값이 정해져있으니 끼워맞춰 답이 나온코드
//배열안의 값들이 변하면 잘못된 답이 나옴
int arr[] = { 10, 20, 30, 40, 20 };
int b[] = { 10, 3, 20, 10, 20, 50 };
int value = 0;
for (int i = 0; i < arr.length; i++) {
	for (int j = 0; j < b.length; j++) {
		if ( arr[i] == b[j] ) { // 배열이 하나 더 있으면 쉽겠다만...
			value = arr[i];
			b[j] = 0;
		}
	}
	if (arr[i] == value) {
		arr[i] = 0;
	}
}
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(b));

문제에서 제시된 배열의 값들이 정해져있어서 어떻게 끼워맞춰 답은 나온코드인데 문제는 arr배열의 값이 변하면 틀린 답이 나와버린다.
결국은 잘못된 코드
그래서 다시 고민해보고 작성한 코드는 아래와 같다.

int arr1[] = { 10, 20, 30, 40, 20 };
int b[] = { 10, 3, 20, 10, 20, 50 };
// 1. 첫번째 반복문  반만 돌릴 배열 선택 ===> arr1[] 
// 2. arr1.length/2를 조건식에 넣으면 어색하니 변수 생성
int halfLength = arr1.length/2;
for (int i = 0; i <= halfLength; i++) { 
	// 2개 이상일때 세줄 변수
	int count = 0;
	int index = arr1.length-1;
	for (int j = 0; j < b.length; j++) { // b[] 은 전체적으로 검사해야함 ===> 반복될때마다 count+1
		//===> 그렇다면 count가 1이상일때 arr배열의 뒤에서부터는 어떻게 없애나? ==> 그때마다 두번째 반복문에서 마지막 인덱스 빼며 접근
		if (arr1[i] == b[j]) { 
			b[j] = 0;
			count++;
		}
		if (count >= 1 && arr1[index] == b[j]) {
			arr1[index] = 0;
			index--;
		}
	}
	if (count != 0) {
		arr1[i] = 0;
	}
}
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(b));

첫번째로는 기준이 되는 첫번째 반복문, 즉, 겉으로 크게 돌 배열을 선택한다.
두번째로 첫번째 반복문을 반만 돌리기 위해 조건식을 배열크기/2로 설정했다. 사족으로 조건식에 arr1.length/2를 넣기는 좀 배열/2 값을 지니는 변수를 만들었다. 있어도 그만 없어도 그만...
세번째로 전체검사할 b배열을 두번째 반복문에 넣는다. 이는 arr의 인덱스가 1씩 증가할때마다 전체검사를 하기 위함이다.
네번째로 b배열에 중복되는 값이 있으면 count를 1증가시키고 b배열의 중복값을 없앤 후, arr배열에서 첫번째 for문 범위 바깥의 인덱스를 감소시키며 중복값이 있는지 확인해준다.
다섯번째로 기준이 되는 arr배열의 i번지 값을 0으로 바꿔준다.
이 코드로 실행하면 b배열의 크기나 값이 변해도 무사히 중복값들이 0으로 바뀐다.

처음에는 값으로 접근해봤는데 배열을 다시만들고 또 다시만드는 것은 원하는 방식이 아니어서 고민을 해봤다. 배열도 몇개 새로 만들어보고 위의 끼워맞춘 코드도 작성해보고 시도를 한 끝에 기준이 될 배열을 반만 돌린 후 중복값이 있을때 나머지 반을 다른 두번째 반복문에서 검사하면 되지 않을까 싶어 해봤고 이는 괜찮은 접근법이었다. 다행이다...
~~

6/8 추가
망했다.
이중 반복문 안의 조건문도 망했고 그냥 끼워맞추기에 얻어걸린거였다... 배열 값을 바꾸니 안됐는데 과연 해결할 수 있을까

9. 팰린드롬1

팰린드롬이란?
앞에서부터 읽을 때와
뒤에서부터 읽을 때 똑같은 숫자가 나오면 팰린드롬이다
예) 2112
예) 12321

// 배열들이 각각 팰린드롬인지 아닌지 출력하시요.
int arr1[] = { 1, 5, 4, 5, 3, 2, 2, 3, 5, 4, 5, 1 };
int arr2[] = { 1, 5, 4, 5, 3, 2, 3, 5, 4, 5, 1 };
// 크기 반 쪼갠후 두번째 for문에서 인덱스 끝부터 돌기... 아님말구
int halfLength = arr1.length/2;
int index = arr1.length-1;
boolean check = false;
for (int i = 0; i <= halfLength; i++) {
	if (arr1[i] == arr1[index]) {
		check = true;
	} else {
		check = false;
		break;
	}
	index--;
}
if (check == true) {
	System.out.println("arr1 팰린드롬이 맞다");
} else {
	System.out.println("아니다");
}
halfLength = arr2.length/2;
index = arr2.length-1;
check = false;
for (int i = 0; i < arr2.length; i++) { // 홀수일때 이상을 조건으로 하면 i번째 인덱스 out
	if (arr2[i] == arr2[index]) {
		check = true;
	} else {
		check = false;
		break;
	}
	index--;
}
if (check == true) {
	System.out.println("arr2도 팰린드롬이 맞다");
} else {
	System.out.println("아니다");
}

배열의 반만큼 돌리되 배열의 끝 인덱스부터 반복하며 같은 값인지 확인하면 되던 문제.

10. 펠린드롬2

int arr[] = { 1, 3, 0, 0, 2, 1, 2, 3, 0 };
int count = 0;
for (int i = 0; i < arr.length; i++) { // 3,2 새 배열로 안빼내고 따로 가능은 하지만 굳이 그렇게 하는걸 권하진 않는다고...
	// 3과 2배열 크기 구하기
	if (arr[i] == 2 || arr[i] == 3) {
		count++;
	}
}
//		System.out.println(count);
int[] sample = new int[count];
int sampleIndex = 0;
for (int i = 0; i < arr.length; i++) {
	if (arr[i] == 2 || arr[i] == 3) {
		sample[sampleIndex] = arr[i];
		sampleIndex++;
	}
}
System.out.println(Arrays.toString(sample));
int halfLength = sample.length/2;
int down = sample.length-1; // 감소할 인덱스
int check = 0;
for (int i = 0; i < halfLength; i++) {
	if (sample[i] == sample[down]) {
		check ++;
	}
	down--;
}
if (check == halfLength) {
	System.out.println("펠린드롬이 맞다");
}

이 문제를 맞딱뜨렸을때 고민을 했다. 2와 3만을 지니는 배열이 필요한가 아닌가 왠지 될거같은데 고민을 하다가 새로 2와3만을 지니는 배열을 만드는 것이 낫다고 생각들어 새로 만들어주고 펠린드롬인지 확인했다.

0개의 댓글