변수?.멤버?.는 C#의 null 조건 연산자 (null-conditional operator)입니다. 이 연산자는 객체가 null인지 확인한 다음, 안전하게 멤버 또는 메서드에 접근할 수 있도록 도와줍니다.
l1?.next는 다음과 같이 동작합니다:l1이 null이 아니면 l1.next에 접근합니다.l1이 null이면 null을 반환합니다.즉, 이 연산자는 null 참조로 인한 런타임 예외 (NullReferenceException)를 방지합니다.
https://devblogs.microsoft.com/dotnet/default-implementations-in-interfaces/
https://andrewlock.net/understanding-default-interface-methods/
인터페이스는 구현 없고 다중 상속 가능하고
추상 클래스는 구현 있고 다중 상속 불가능하다고 봤는데
더 찾아보니까 C#이나 Java나 버전 올라오면서 인터페이스에서도 구현하는거 가능하다고 함
대신 상속은 안됨
인터페이스 > 추상 클래스 > 클래스 이런 식으로 상속받았다면
클래스에서 인터페이스를 명시적으로 상속받아야 구현한 거 상속받을 수 있음
죽음의 다이아몬드 문제 발생할 수 있음 (뭘 실행해야되는 건데?)
public class Solution {
public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
int remain = 0;
int power_ten = 1;
ListNode l1Node = l1;
ListNode l2Node = l2;
ListNode result = new ListNode();
while (l1Node.next != null)
{
int cur_sum = l1Node.val + l2Node.val + remain;
remain = 0;
if (cur_sum >= 10)
{
cur_sum -= 10;
remain = 1;
}
l1Node = l1Node.next;
l2Node = l2Node.next;
result.val = cur_sum;
result.next = new ListNode();
result = result.next;
}
return result;
}
}
nullref가 왜 뜨는거임?? 했는데
l1과 l2의 길이가 같다는 보장이 없었음
public class Solution {
public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
int remain = 0;
int power_ten = 1;
ListNode l1Node = l1;
ListNode l2Node = l2;
ListNode result = new ListNode();
while (l1Node != null || l2Node != null)
{
int l1Val = (l1Node != null) ? l1Node.val : 0;
int l2Val = (l2Node != null) ? l2Node.val : 0;
int cur_sum = l1Val + l2Val + remain;
if (cur_sum >= 10)
{
cur_sum -= 10;
remain = 1;
}
remain = 0;
if (l1Node != null) l1Node = l1Node.next;
if (l2Node != null) l2Node = l2Node.next;
result.val = cur_sum;
result.next = new ListNode();
result = result.next;
}
return result;
}
}
이젠 답은 나오는데

이따구로 나옴
처음을 줘야 하는데 마지막을 줘서 그런건가?
: 그럼 첫번째 노드만 저장해놓으면 되겠구나
근데 그렇다고 하더라도 8이 나와야지 왜 0이 찍힘?
: 당연한거지 result는 마지막에 무조건 0이 될테니까
public class Solution {
public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
int remain = 0;
ListNode l1Node = l1;
ListNode l2Node = l2;
ListNode firstNode = new ListNode();
ListNode result = firstNode;
while (l1Node != null || l2Node != null || remain > 0)
{
int l1Val = (l1Node != null) ? l1Node.val : 0;
int l2Val = (l2Node != null) ? l2Node.val : 0;
int cur_sum = l1Val + l2Val + remain;
remain = 0;
if (cur_sum >= 10)
{
cur_sum -= 10;
remain = 1;
}
result.val = cur_sum;
if (l1Node != null) l1Node = l1Node.next;
if (l2Node != null) l2Node = l2Node.next;
if (l1Node != null || l2Node != null || remain > 0)
{
result.next = new ListNode();
result = result.next;
}
}
return firstNode;
}
}
if문 떡칠해서 풀긴 함
remain > 0 조건을 떠올리는것과
while문에도 넣어줘야 한다는 점을 놓쳐서 살짝 시간 소요
while (true)
{
int l1Val = (l1Node != null) ? l1Node.val : 0;
int l2Val = (l2Node != null) ? l2Node.val : 0;
int cur_sum = l1Val + l2Val + remain;
remain = 0;
if (cur_sum >= 10)
{
cur_sum -= 10;
remain = 1;
}
result.val = cur_sum;
if (l1Node != null) l1Node = l1Node.next;
if (l2Node != null) l2Node = l2Node.next;
if (l1Node == null && l2Node == null && remain == 0)
break;
result.next = new ListNode();
result = result.next;
}
if문 호출 횟수 개선해서 시간 좀 줄임
public class Solution
{
public ListNode AddTwoNumbers(ListNode l1, ListNode l2, int carry = 0)
{
if (l1 == null && l2 == null && carry == 0) return null;
int total = (l1 != null ? l1.val : 0) + (l2 != null ? l2.val : 0) + carry;
carry = total / 10;
return new ListNode(total % 10, AddTwoNumbers(l1?.next, l2?.next, carry));
}
}
더 빠르게 짠 사람들은 어떻게 풀었나 봤더니
함수 자체를 재귀 함수로 바꿔버림. ?이라는 이상한 문법도 사용.
멤버나 메서드 접근하기 전에 null check하는 문법이라는데 실사용 가능성도 있을지도?
remain = 0;
if (cur_sum >= 10)
{
cur_sum -= 10;
remain = 1;
}
여기서 remain = 0;은 인자에서 초기화해버리고
10보다 크면 다음 자리수의 1로 설정하는 건 carry = total / 10으로 해결함.