
* 문제
정수 배열 nums와 정수 target이 주어진다.
두 수를 더해 target이 되는 두 숫자의 인덱스를 반환하라.
단, 같은 원소를 두 번 사용할 수는 없다.
정답은 어떤 순서로 반환해도 상관 없다.
* 예시 1
입력:
nums = [2,7,11,15], target = 9
출력:
[0,1]
설명: nums[0] + nums[1] = 9 이므로 [0, 1]을 반환.
* 예시 2
입력:
nums = [3,2,4], target = 6
출력:
[1,2]
* 예시 3
입력:
nums = [3,3], target = 6
출력:
[0,1]
* 제약 조건
2 <= nums.length <= 10⁴
-10⁹ <= nums[i] <= 10⁹
-10⁹ <= target <= 10⁹
가능한 정답은 오직 하나만 존재한다.
반복문으로 nums 리스트를 돌면서 더해주고 더한 값이 target 값이라면 해당 인덱스를 기록하는 식으로 생각을 했다.
class Solution {
List<int> twoSum(List<int> nums, int target) {
Set<int> idexList = {};
for (var i = 1; i < nums.length; i++) {
for (var j = 0; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
idexList.addAll([i, j]);
}
}
}
return idexList.toList();
}
}
그래서 만든 게 요친구 그런데 nums = [-1,-2,-3,-4,-5] target = -8을 만나면 정답은 [2,4]지만 내 코드는 [2,4,3]을 반환하는 문제가 생겼다. i랑 j랑 안 겹치게 하려고 i를 1부터 시작하게 했는데 그게 문제였던 것 같다. 그래서 if문에 조건을 하나 더 추가했다.
class Solution {
List<int> twoSum(List<int> nums, int target) {
Set<int> idexList = {};
for (var i = 0; i < nums.length; i++) {
for (var j = 0; j < nums.length; j++) {
if (i != j && nums[i] + nums[j] == target) {
idexList.addAll([i, j]);
}
}
}
return idexList.toList();
}
}
i랑 j랑 같지 않다는 조건도 넣어서 검사해서 제출했더니 헉.. 성공은 했지만 런타임이 192ms가 걸렸다;; 흐린 눈 하고 넘어갔다...
“스크롤 가능한 리스트”를 슬리버 형태로 제공하는 위젯.
ListView가 내부적으로 쓰는 구조의 기본 단위
스크롤 전체가 Sliver 방식으로 관리됨 → 성능 좋음
다른 Sliver들과 자연스럽게 섞임
SliverChildBuilderDelegate 또는 SliverChildListDelegate로 아이템 구성
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
height: 80,
color: Colors.grey[300],
margin: const EdgeInsets.all(8),
child: Text('Item $index'),
);
},
childCount: 20,
),
)
그리드 레이아웃을 Sliver 방식으로 표현한 것
GridView의 Sliver 버전
SliverList와 동일하게 스크롤을 Sliver 구조로 효율적으로 처리
여러 Sliver들과 자연스럽게 조합 가능
SliverGrid(
delegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
color: Colors.blue,
);
},
childCount: 30,
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 1,
),
)
| 비교 항목 | ListView / GridView | SliverList / SliverGrid |
|---|---|---|
| 구조 | 단일 스크롤 위젯 | Sliver 구조 (여러 스크롤 조합 가능) |
| AppBar와 연동 | AppBar 아래 고정 | SliverAppBar와 자연스럽게 연동 (확장/축소 가능) |
| 여러 섹션 결합 | 어려움. SingleChildScrollView + Column 필요 | Sliver들끼리 바로 이어붙이면 됨 |
| 용도 | 단일 리스트/그리드 | 복합 스크롤 화면(ex. 앱 메인 페이지) |
SliverAppBar + 리스트/그리드 조합
Pinterest 스타일 화면
헤더 → 리스트 → 배너 → 그리드 → 푸터 이런 다양한 섹션 있는 스크린
스크롤에 따라 UI 변하는 화면
그냥 리스트, 그리드만 있다
SliverAppBar 안 씀
복잡한 스크린 구조가 아님
이런 경우엔 그냥 ListView 써도 됨
네트워크/비동기 이미지가 로드될 때 플레이스홀더 → 실제 이미지로 부드럽게 페이드인(교차 페이드) 시켜주는 위젯
내부적으로 ImageProvider(예: AssetImage, NetworkImage, MemoryImage)를 사용
FadeInImage({ required ImageProvider placeholder, required ImageProvider image, ... }) — 직접 ImageProvider 전달
FadeInImage.assetNetwork({ required String placeholder, required String image, ... }) — 흔하게 쓰는 편리 생성자
FadeInImage.memoryNetwork({ required Uint8List placeholder, required String image, ... }) — 메모리 바이트 플레이스홀더 사용
placeholder / image — 필수, ImageProvider
width, height, fit — 레이아웃 제어
fadeInDuration / fadeOutDuration — 애니메이션 시간 (Duration)
fadeInCurve / fadeOutCurve — 애니메이션 커브
placeholderScale — 플레이스홀더의 스케일링
FadeInImage.assetNetwork(
placeholder: 'assets/placeholder.png',
image: 'https://picsum.photos/300/300',
width: 120,
height: 120,
fit: BoxFit.cover,
fadeInDuration: Duration(milliseconds: 300),
);
과제 제출을 완료해서 튜터님께 따로 과제를 받았다. 플러터로 클론 어플 구현해보는 과제였는데 아직 헷갈리는 위젯들이 몇 가지 있어서 주말에 정리해봐야겠당~