지식/알고리즘

145일 (2074. Reverse Nodes in Even Length Groups) LinkedList, 정말 어려움

매우 강한사람 2024. 2. 12. 10:27

You are given the head of a linked list.

The nodes in the linked list are sequentially assigned to non-empty groups whose lengths form the sequence of the natural numbers (1, 2, 3, 4, ...). The length of a group is the number of nodes assigned to it. In other words,

  • The 1st node is assigned to the first group.
  • The 2nd and the 3rd nodes are assigned to the second group.
  • The 4th, 5th, and 6th nodes are assigned to the third group, and so on.

Note that the length of the last group may be less than or equal to 1 + the length of the second to last group.

Reverse the nodes in each group with an even length, and return the head of the modified linked list.

 

Example 1:

 

Input: head = [5,2,6,3,9,1,7,3,8,4]
Output: [5,6,2,3,9,1,4,8,3,7]
Explanation:
- The length of the first group is 1, which is odd, hence no reversal occurs.
- The length of the second group is 2, which is even, hence the nodes are reversed.
- The length of the third group is 3, which is odd, hence no reversal occurs.
- The length of the last group is 4, which is even, hence the nodes are reversed.

Example 2:

Input: head = [1,1,0,6]
Output: [1,0,1,6]
Explanation:
- The length of the first group is 1. No reversal occurs.
- The length of the second group is 2. The nodes are reversed.
- The length of the last group is 1. No reversal occurs.

Example 3:

Input: head = [1,1,0,6,5]
Output: [1,0,1,5,6]
Explanation:
- The length of the first group is 1. No reversal occurs.
- The length of the second group is 2. The nodes are reversed.
- The length of the last group is 2. The nodes are reversed.

 

Constraints:

  • The number of nodes in the list is in the range [1, 10^5].
  • 0 <= Node.val <= 10^5

 

- 접근방법

 

더 나은 방법을 찾기위해 몇시간 내내 고민하였다... 생소한데다가 어렵기까지 했다.

 

현재 그룹 크기(currentGroupSize) 는 1부터 1씩 누적되서 증가한다.
currentGroupSize가 짝수거나, 현재그룹의 노드 개수가 짝수일때 현재 그룹의 노드들을 역순으로 수정한다.

(head.next == null 일수도 있으니까 현재그룹의 노드개수와 currentGroupSiz는 항상 동일하지는 않다.)

 

0. 연결리스트 내부를 수정하려면

(이전그룹의 마지막 노드 + 역순으로 재배열 된 연결리스트 시작노드와 끝 노드 +다음에 시작될 노드) 가 필요하다.

 

1. getGroupEndNode() 메서드는 현재 그룹의 마지막 노드를 리턴한다.

( currentGroupSize에 속하는 마지막 노드거나 혹은 node.next == null인 마지막 노드거나)

 

2. reverseGroup() 메서드는 역순으로 재배열 될 시작노드, 역순으로 재배열 될 노드의 개수를 매개변수로 하여 주어진 조건 내의 연결리스트를 역순으로 수정한다.

 

3. 현재그룹(currentGroupSize)에 속하는 노드들의 범위를 구한다. 

 

4. 현재그룹(currentGroupSize)에 속하는 노드의 개수가 짝수라면,  이전그룹의 마지막 노드(prevNode) + reversed[0](역순으로 뒤집힌 연결리스트의 시작노드) + reversed[1] (역순으로 뒤집힌 연결리스트의 마지막노드)를 연결한다.

 

5. 현재그룹(currentGroupSize)에 속하는 노드의 개수가 홀수라면,  이전 마지막 노드의 다음노드로 현재 그룹을 잇는다.

 

 

 

- 코드

class Solution {
    public ListNode reverseEvenLengthGroups(ListNode head) {
        ListNode answer = new ListNode(0, head);
        ListNode prevNode = answer;
        int currentGroupSize = 1;

        while (head != null) {
            ListNode currStartNode = head;
            int size = 0;

            while (head != null && size < currentGroupSize) { // 3
                head = head.next;
                size++;
            }

            if (size % 2 == 0) { // 4
                ListNode[] reversed = reverseGroup(currStartNode, size);
                prevNode.next = reversed[0];
                prevNode = reversed[1];
            } else {
                prevNode.next = currStartNode; // 5
                prevNode = head == null ? currStartNode : getGroupEndNode(currStartNode, size);
            }

            currentGroupSize++;
        }

        return answer.next;
    }

    private ListNode[] reverseGroup(ListNode head, int size) { // 2
        ListNode tempHead = head;
        ListNode startNode = null;
        ListNode endNode = head;
        int cnt = 0;

        while (cnt < size) {
            ListNode nextNode = tempHead.next;
            tempHead.next = startNode;
            startNode = tempHead;
            tempHead = nextNode;
            cnt++;
        }
        endNode.next = tempHead;
        return new ListNode[]{startNode, endNode};
    }

    private ListNode getGroupEndNode(ListNode start, int size) { // 1
        while (start != null && size > 1) {
            start = start.next;
            size--;
        }
        return start;
    }
}

 

 

노드가 짝수개수 그룹일때 직접 역순으로 수정하면 현재 그룹의 노드는 역순으로 수정되었는데, 가르키는 포인터는 역순으로 수정되기 이전 값을 가르킨다.

 

포인터명(startNode, endNode 등)으로 현재 그룹의 시작노드와 끝 노드를  포인터로 기억하기 보다는 배열에 수정된 후 시작노드, 끝노드를 기억하는 것이 좋다.

그리고 메모지에 손으로 수정 이전 포인터와 수정 후 포인터 위치도 작성하면서 확인해보고 헷갈림을 방지할 수 있다.

 

 

 

 

https://leetcode.com/problems/reverse-nodes-in-even-length-groups/

 

LeetCode - The World's Leading Online Programming Learning Platform

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com