반응형

저번 포스팅에서는 프로젝트 세팅을 했는데 일단 거지같은 모양새다.

 

밑에 푸터도 주고 위에 헤더도 설정해보자

 

1. layout 나누기

header / body / footer 영역을 나눠보자.

우선 home : Scaffold 설정을 하고 appBar / body / bottomNavigationBar 로 나누면 된다

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              backgroundColor: Colors.white,
              title: SizedBox(
                height: 40,
                child: TextField(
                  decoration: InputDecoration(
                      hintText: '검색어를 입력하세요', //힌트 텍스트
                      filled: false, //배경색 활성화
                      fillColor: Colors.white,
                      suffixIcon: const Icon(Icons.search, color: Colors.grey),
                      enabledBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20),
                          borderSide: const BorderSide(color: Colors.grey, width: 1)
                      ),
                      focusedBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20),
                          borderSide: const BorderSide(color: Colors.grey, width: 1)
                      ),
                      contentPadding: const EdgeInsets.only(left: 15, right: 10)
                  ),
                ),
              ),
            ),
            body: Container(
              width: 150, height: 50, color: Colors.black,
              margin: const EdgeInsets.fromLTRB(10, 10, 10, 10),
            ),
            bottomNavigationBar: const BottomAppBar(
                child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      Icon(Icons.star),
                      Icon(Icons.confirmation_num_sharp),
                      Icon(Icons.co2_outlined)]
                )
            )
        )
    );

  }
}

 

 

대충이렇게하면 뭔가 많이본 모양이 나오긴 한다

input 필드를 생성하고 그 안에 hint 와 suffix icon 돋보기 이미지를 설정하였다

 

하지만 상단의 시간쪽이랑 로고도 넣으면 좋을것같다.

 

2. Header 꾸미기

appBar 에 leading 속성을 추가해서 로고 이미지를 넣어보자.

 

이미지를 넣으려면 pubspec.yaml 에 이미지 root 설정을 해야한다.

assets 설정을 추가하자

...

flutter:
  assets:       # <- 여기 추가
    - assets/    # <- 여기 추가
  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true
  ....

 

그리고 인텔리제이기준 우측상단에 pub get, pub upgrade를 한번씩 눌러주자

 

그리고 재실행해주면 이제뭔가 앱같긴 하다.

 

상단에 회색영역도 지워보자

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  // 상태 바 배경 색상 변경 (흰색으로 설정)
  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
    statusBarColor: Colors.white, // 상태 바 색상을 흰색으로 설정
    statusBarIconBrightness: Brightness.dark, // 상태 바 아이콘을 어두운 색으로 설정 (흰색 배경에 어울리도록)
  ));

  runApp(const MyApp());
}

 

이렇게까지하면 헤더는 정리된 느낌 근데 폰트가 맘에안든다.

 

국룰폰트 Noto Sans Kr 을 넣어보자

 

3. 폰트 추가

https://fonts.google.com/noto/specimen/Noto+Sans+KR

 

Noto Sans Korean - Google Fonts

Noto is a global font collection for writing in all modern and ancient languages. Noto Sans KR is an unmodulated (“sans serif”) design for the Korean language u

fonts.google.com

 

여기서 get Font -> Download All

해서 모든 ttf 파일을 다운로드하고 프로젝트의 root 경로에 fonts 폴더생성 후 모두 집어넣는다

 

이걸이제 어케쓰냐면, pubspec 에 선언하고 사용하면 된다

pubspec 하단에 example이 나와있긴한데, 만드려면 복잡시러우니까 그냥 밑에 복사해서 쓰자

 

헷깔릴까봐 flutter 부터 복사해봄

flutter:
  assets:
    - assets/

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  # assets:
  #   - images/a_dot_burr.jpeg
  #   - images/a_dot_ham.jpeg

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  fonts:
    - family: NotoSansKR
      fonts:
        - asset: fonts/NotoSansKR-Thin.ttf
          weight: 100
        - asset: fonts/NotoSansKR-ExtraLight.ttf
          weight: 200
        - asset: fonts/NotoSansKR-Light.ttf
          weight: 300
        - asset: fonts/NotoSansKR-Regular.ttf
          weight: 400
        - asset: fonts/NotoSansKR-Medium.ttf
          weight: 500
        - asset: fonts/NotoSansKR-SemiBold.ttf
          weight: 600
        - asset: fonts/NotoSansKR-Bold.ttf
          weight: 700
        - asset: fonts/NotoSansKR-ExtraBold.ttf
          weight: 800
        - asset: fonts/NotoSansKR-Black.ttf
          weight: 900

 

그리고 main.dart 에서 hoem 상단에 theme 을 추가하자

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
        theme: ThemeData( //추가
            fontFamily: 'NotoSansKR'
        ),
        home: Scaffold(
        ...생략

 

 

4. Footer 추가

푸터를 추가한다는것은 클릭할때마다 페이지가 바뀌면 좋겠기 때문이다.

flutter 페이지 이동방식에는 두가지가 있다.

 

header, footer 를 유지하지않고 전체페이지가 바뀌는방식과 header,footer를 고정시키고 body 만 바뀌는 방식이 있는데, 이번엔 body 만 바꿔보겠다.

 

푸터에 탭을 3개둔다고 가정하고 이동할 페이지를 3개 더 생성해보자

 

main.dart는 페이지변경을 관장하는곳으로 인식하고 나머지페이지는 이동할 대상이다.

나는 달력을 넣을것이기때문에 home, calendar, mypage 이렇게 3개로 만들어봤다.

 

home.dart

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('홈 화면'),
      ),
    );
  }
}

 

calendar.dart

import 'package:flutter/cupertino.dart';

class CalendarScreen extends StatelessWidget {
  const CalendarScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('달력 화면'),
    );
  }
}

 

mypage.dart

import 'package:flutter/material.dart';

class MyPageScreen extends StatelessWidget {
  const MyPageScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Text('여기는 마이페이지 화면입니다!'),
      ),
    );
  }
}

 

이렇게 3개를 만들었으면 이제 main.dart에 이어보자

 

MyApp build 부분을 이렇게 간단하게 바꿔놓는다

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(fontFamily: 'NotoSansKR'),
      home: MainScreen(), // MainScreen이 앱의 첫 화면이 됨
    );
  }
}

 

그리고 MainScreen 을 정의해준다.

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(fontFamily: 'NotoSansKR'),
      home: MainScreen(), // MainScreen이 앱의 첫 화면이 됨
    );
  }
}

class MainScreen extends StatefulWidget {
  const MainScreen({super.key});

  @override
  _MainScreenState createState() => _MainScreenState();
}

 

이제 MainScreen State 에 들어갈 요소들을 넣어주자

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(fontFamily: 'NotoSansKR'),
      home: MainScreen(), // MainScreen이 앱의 첫 화면이 됨
    );
  }
}

class MainScreen extends StatefulWidget {
  const MainScreen({super.key});

  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  int _selectedIndex = 0;

  static final List<Widget> _widgetOptions = <Widget>[
    HomeScreen(), //import 필요 
    CalendarScreen(),  //import 필요
    MyPageScreen(),  //import 필요
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Header(),
      body: _widgetOptions.elementAt(_selectedIndex),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '홈',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.calendar_today),
            label: '달력',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '마이페이지',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blue,
        onTap: _onItemTapped,
      ),
    );
  }
}

 

요로코롬하면 탭 클릭 시 페이지 변경 완료

728x90

'Mobile > Hybrid' 카테고리의 다른 글

Flutter 프로젝트 시작하기 (intelliJ)  (1) 2025.03.25
Cordova (코르도바) 시작하기  (1) 2024.09.06
반응형

 

하이브리드앱으로 코르도바를 쓰다가 html, css, js 범벅이 힘들어서 flutter를 공부해봤다.

 

기본적인 jdk, gradle 은 있다고 생각하겠다.

 

1. Flutter SDK 다운로드

https://docs.flutter.dev/release/archive

 

Flutter SDK archive

All current Flutter SDK releases: stable, beta, and main.

docs.flutter.dev

 

(Windows 기준)

이곳에서 stable SDK 버전을 다운받고 개인 PC 내 특정 폴더에 위치시킨다.

 

그리고 환경변수 PATH 에 해당 위치를 등록.

나의 경우는 D:\bin\flutter\bin 이었고 bin 까지만 하면된다

 

2. IntelliJ 플러그인 flutter 추가

File -> Setting -> Plugins -> Dart, Flutter 플러그인을 추가한다.

 

3. 프로젝트 생성

New Project -> Flutter 생성한다.

이때 Flutter SDK Path 에 내가 환경변수에 설정했던 flutter 위치가 와있으면 성공

 

 

패키지명 설정해서 대강 만들고 실행하면 된다.

 

나는 ios, android 만 만들거라서 이렇게했는데

빌드할때마다 모바일로 보지말고 web을 선택해서 browser도 확인하는것도 좋을것같다.

4. 개발시작

main.dart 가 첫 시작이다.

보통 lib > main.dart  얘를 index로 보는거같고 각종 header, footer 와 같은 layout 성 화면들을 [widgets]폴더에,

기타화면은 [screens] 폴더에 넣는것같다

 

하여간 처음 실행시키면 main.dart 에 알수없는 코드가 많은데 싹다지우자

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {

    return const MaterialApp(
        home: Text("test")
    );

  }
}

 

이렇게 설정해주면 아래와 같이 보일것이다.

 

나는 갤럭시 23을 테스트모델로 작업했고, release 버전이 아닌 이상, 보이는바와 같이 우측상단에 DEBUG 라고 보인다.

 

다음포스팅에선 페이지이동과 layout 설정을 해보겠다

728x90

'Mobile > Hybrid' 카테고리의 다른 글

Flutter 프로젝트 시작하기 - 페이지 이동  (0) 2025.03.25
Cordova (코르도바) 시작하기  (1) 2024.09.06
반응형

 

싱글톤 패턴은 소프트웨어 디자인 패턴중 하나이다.

 

주로 사용되는 경우는 단 하나만 존재해야되는 물건이 있을 때!

프로그램 내부에서 단 1개만 생성됨을 보장하며 멀티쓰레드에서 이 객체를 동시에 접근하는 경우에 발생하는 동시성 문제를 해결해준다.

 

말로설명하면 어렵고 코드를 보면 쉽다.

class Order {
    public void start() {
        A a = A.getInstance();
        A b = A.getInstance();
        // 확인
        System.out.println(a == b); // true
    }
}

 

만약 이렇게 있다고 치면, a 와 b 는 같은 객체를 보고있게 된다.

이런 로직을 만들 필요가 있을때 싱글톤패턴을 사용한다.

 


1. 기본적인 구현방법 (리소스낭비)

public class A {

	private A() {
           System.out.println("Hello singleton!!");
	}

	private static A singleton = new A(); //객체생성

	public static A getInstance() {
            return A;
	}

}

 

private 생성자를 사용하여 외부에서의 생성을 막은것이 포인트다

단점으로는 클래스가 로드될때 객체가 생성되므로 리소스 낭비가 있을 수 있다.

 

그렇다면 어떻게 개선할수있을까?

 

2. 기본적인 구현방법 (리소스낭비 줄임)

public class A {
    // 단 1개만 존재해야 하므로 static
    private static A a;

    // private로 외부생성을 막음
    private A() {
       System.out.println("Hello singleton!!");
    }

    //외부에서는 getInstance로 접근
    public static A getInstance() {
      if (instance == null){
          instance = new A();
      }
      return instance; 
    } 
}

 

1) getInstance()

 - static을 쓰지않으면 외부에서 사용할때

new A().new getInstance()

이렇게 새로운 인스턴스를 선언하면서 써야하기때문에 싱글톤이 보장되지 않는다.

따라서 static을 사용하고 if 문을 통하여 기존에 불려진 instance가 없다면 생성, 있다면 기존 instance를 return

 

하지만 단점!

이 경우 Multi Thread 환경에서 Thread-safe 를 보장해주지 않는다.

n개의 사용자가 동시에 getInstance를 했을때 new A() 를 n번 생성할수도있다.

 

이를 막기위해서 Synchronized, Double check 등을 사용해서 막아볼수도 있겠지만, 가장많이 쓰이는 방법은 아래와 같다.

 

3. LazyHolder 싱글톤 패턴 ✔️

public class A {

    private A() {
       System.out.println("Hello singleton!!");
    }
    
    private static class LazyHolder() {
        private static final A instance = new A();
    }

    public static A getInstance() {
        return LazyHolder.instance;
    }
    
}

 

 

훨씬 코드가 예뻐진것을 볼수있다.

 

해당 클래스가 로드되더라도 getnstance() 메서드가 호출될때까지 로드되지 않으므로 리소스 낭비도 줄이고

 

A.getInstance() 를 호출할때마다 동일한 instance가 변환된다. 왜냐! private static final 로 선언했기때문!

 

사용은 아래와 같이 쓰면된다

public static void main(String[] args) {
	A a = A.getInstance();
}

Spring 의 경우에는 static 기반의 싱글톤 구현을 지양하고있으며 더욱 간단하게 쓸수있다.

 

Spring - @Autowired 사용

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class A {
    public A() {
        System.out.println("Hello singleton!!");
    }
}

@Component
public class Main {
    @Autowired
    private A a; // A의 싱글톤 인스턴스가 주입됨

    public void display() {
        System.out.println(a);
    }
}

// 메인 메서드
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        Main main = context.getBean(Main.class);
        main.display();

        // 다시 가져와서 같은 인스턴스인지 확인
        Main anotherMain = context.getBean(Main.class);
        System.out.println(main.a == anotherMain.a); // true, 같은 인스턴스
    }
}

 

위와 같이 인스턴스 필드로 의존성 주입을 사용하는 경우, 싱글톤 패턴이 유지된다.

Spring 컨테이너는 @Component, @Service, @Repository, @Controller 등으로 정의된 클래스의 인스턴스를 싱글톤으로  관리한다

 

항상 어노테이션을 사용하여 써왔기때문에 싱글톤 패턴을 정석으로 봤을때 생소했던것같다.

728x90

'CS' 카테고리의 다른 글

종속성, 의존성  (0) 2024.10.31
반응형

 

항상 사용하고있던 종속성, 의존성에 대한 고찰.

 

종속성

: 한 클래스가 다른 클래스나 기능을 필요로 할때 발생하는 관계.

예를들어 class B 가 class A 의 변수 혹은 함수에 의존한다면, class B는 class A의 종속성을 가진다고 할 수 있다.

 

의존성

: 종속성을 관리하는 방식.

흔히 알고있는 DI (Dependency Injection) 의존성 주입 이라고한다.

 

예를들어 class B에서 class A를 선언하지않고, 외부에서 class A의 인스턴스를 주입받으면 class A의 속성이나 인스턴스 그대로 사용가능하다.

 

이것을 왜 헷깔리고 자주 잊는가?

나는 개인적으로 외부 class를 선언하고 사용하는것에 너무 익숙해져있기 때문이다.

 

그러한 행위가 가능한 이유는 전부 DI 덕분이라는것을 다시 생각해보았다. 

728x90

'CS' 카테고리의 다른 글

싱글톤 패턴의 이해와 응용  (0) 2024.10.31
반응형

작업은 vscode 에서 진행한다.

만약 없다면 무료 툴 이므로 다운로드!

 

1. node js 설치

https://nodejs.org/en

 

 

2.  cordova 설치

cmd 창에서 진행하면 된다

$ npm install -g cordova

 

3. cordova 프로젝트 생성

내가원하는 폴더로 이동 후 아래 커맨드 실행

$ cordova create [프로젝트명] [패키지명] [프로젝트명]

ex)
$ cordova create cordova1 com.example.test cordova1

 

이렇게 프로젝트가 생성된다

 

처음에는 기본적으로 www 즉 웹만 생성되며 실행시켜볼수도있다.

 

vscode 플러그인으로 live server 를 추가하고 (구글링) 실행하면 코르도바 이미지가 보인다

 

 

 

4.  Android, iOS platform 추가

아래 커맨드로 안드로이드 소스코드를 추가할 수 있다

$ cordova platform add android

 

마찬가지로 ios로 추가해주면 아래와같이 platoforms에 android 와 ios가 생긴다

 

Android 같은 경우는, java 기반으로 소스코드가 생기는것을 확인해 볼 수 있다.

 

5. project build

 

이제 이것을 vscode에서 그대로 build 하려면 ios의 경우는 맥북이 필요하고

android 는 build 가능하나, 필요한 requirements들이 있다 (jdk 등등) 대신 안드로이드 스튜디오에서 해당프로젝트 실행해도됨

 

$ cordova requirements

 

나의 경우 위에서부터 하나씩 보면 

jdk : 17버전 있음

sdk  : 있음

android target : 없음

gradle : 없음

macOS : 없음

 

이렇게 확인된다

 

특히 android target 부분이나 밑에 gradle 을 보면 please install android studio 라는 부분을 볼수있는데 안드로이드 스튜디오에서 해당 프로젝트를 빌드하는게 속편할것같다

728x90

'Mobile > Hybrid' 카테고리의 다른 글

Flutter 프로젝트 시작하기 - 페이지 이동  (0) 2025.03.25
Flutter 프로젝트 시작하기 (intelliJ)  (1) 2025.03.25
반응형

 

Example 4 : s = "{()}" output = true;

 

예시를 보면 소/중/대괄호가 짝지어서 나오고 Example 4 와 같이 속에있을수도있다.

 

처음에는 String 의 Char.At(i) 가 ( 혹은 { 혹은 [ 일때 Char.At(i +1) 이 ) 혹은 } 혹은 ] 인것을 확인했는데

example 4 때문에 그건 불가능했다.

 

해당문제는 여는 괄호가 나오면 그다음엔 무조건 닫는 괄호가 나와야하기때문에 여는 괄호가 나오면 stack 에 저장해두고, 더이상 여는 괄호가 없으면 stack 에서 가장 나중에 저장된 괄호를 지우는 방식으로 진행했다.

 

class Solution {
    public boolean isValid(String s) {
    	Stack<Character> stack = new Stack<>();
        Map<Character, Character> map = new HashMap<>();
        map.put('(',')');
        map.put('{','}');
        map.put('[',']');
    }
}

 

여는괄호인지를 알기위해서 map을 만들어줬다.

class Solution {
    public boolean isValid(String s) {
    	Stack<Character> stack = new Stack<>();
        Map<Character, Character> map = new HashMap<>();
        map.put('(',')');
        map.put('{','}');
        map.put('[',']');
        
        for (int i=0; i<s.length(); i++) {
        	char c = s.charAt(i);
            
            if (map.containsKey(c)) { //여는 괄호가 나왔다면
            	stack.push(c);
            } else {
            	if (c != map.get(stack.pop()) {
                   return false;
                }
            }
        }
        
        return stack.length == 0;
    }
}

 

 여는 괄호가 나왔다면 stack에 넣어주고 

닫는괄호가 나왔다면, stack에 있는 여는괄호를 불러서 map.get 으로 나온 value와 비교하였다.

 

그리고 모든 닫는괄호가 정상적으로 짝지어나왔다면 stack.length 는 0일 것이므로 return 해줬다.

 

그런데 이렇게 하면 s="]" 일때 .. stack 에도 값이 없기때문에 else 로 빠지지만, 갈곳이없다..!

 

때문에 empty 도 같이 봐준다.

 

class Solution {
    public boolean isValid(String s) {
    	Stack<Character> stack = new Stack<>();
        Map<Character, Character> map = new HashMap<>();
        map.put('(',')');
        map.put('{','}');
        map.put('[',']');
        
        for (int i=0; i<s.length(); i++) {
        	char c = s.charAt(i);
            
            if (map.containsKey(c)) { //여는 괄호가 나왔다면
            	stack.push(c);
            } else {
            	if (stack.isEmpty() || c != map.get(stack.pop())) {
                   return false;
                }
            }
        }
        
        return stack.size() == 0;
    }
}

 

 

 

728x90
반응형

 

 

딱 봤을때 String 으로 만들어서 뒤집어야겠다는 생각을 했다.

 

import java.util.*;

class Solution {
    public long solution(long n) {
        
        //String 배열로 만듦
        String[] arr = String.valueOf(n).split("");
        
        //순서 뒤집음
        Arrays.sort(arr, Comparator.reverseOrder());
        
        //하나의 String으로 변환
        String str = "";
        for (String s : arr) {
            str += String.valueOf(s);
        }
        
        //long 변환
        long answer = Long.parseLong(str);
        return answer;
    }
}

 

그런데 String 으로 변환하는 부분이 마음에 들지않는다.

좀더 간단한 방법이 있을것같고, 내림차순으로 하기위해서 Coparator.reverseOrder() 라는 함수가 있다는것을 외워야한다.

 

다른 사람의 풀이를 살펴보았다.

 

import java.util.*;

class Solution {
    public long solution(long n) {
        
        //String 배열로 만듦
        String[] arr = String.valueOf(n).split("");
        
        //순서 뒤집음
        Arrays.sort(arr);
        
        //하나의 String으로 변환
        StringBuilder sb = new StringBuilder();
        for (String s : arr) sb.append(s);
        
        //long 변환
        long answer = Long.parseLong(sb.reverse().toString());
        return answer;
    }
}

 

StringBuilder 를 사용하면 Comparator.reverseOrder() 이라는 다소 긴 메소드를 기억할 필요없이

new StringBuilder 선언하고 append 로 담은다음에 sb.reverse() 만 해주면 된다.

 

728x90
반응형

public int solution(int n) {
    int answer = 0;

    String str = Integer.toString(n);
    char[] charArr = str.toCharArray();

    for (char c : charArr) {
        int num = Character.getNumericValue(c);
        answer += num;
    }

    return answer;
}

 

n 을 string으로 바꾸고 하나씩 char 로 떼서 형변환 후 더해줬다.

 

이렇게하면 코드가 쓸데없이 길어지므로 String.valueOf()를 사용해서 split 시켜보자.

 

Integer.toString() 도 있지만, 만약 변수가 null 이라면 nullPointException 발생하므로 가급적 String.valueOf() 를 쓰도록 한다.

 

public int solution(int n) {
    int answer = 0;

    String[] str = String.valueOf(n).split("");

    for (String s : str) {
        answer += Integer.parseInt(s);
    }

    return answer;
}

 

이렇게 깔끔하게 변신~

728x90
반응형

간단한 Lv.1

 

x만큼 배열을 늘리면된다.

 

class Solution {
    public long[] solution(int x, int n) {
        long[] answer = new long[n];
        
        return answer;
    }
}

 

우선 array 길이설정을 해주고

 

x를 기존 값에 더해나가고싶다.

class Solution {
    public long[] solution(int x, int n) {
        long[] answer = new long[n];
        
        for (int i=0; i<n; i++) {
           answer[i] = answer[i-1] + x;
        }
        return answer;
    }
}

 

그런데 이렇게하면 첫번째 루프에서는 answer[0] 의 -1 값은 없으므로  0만 따로 설정해준다.

 

class Solution {
    public long[] solution(int x, int n) {
        long[] answer = new long[n];
        answer[0] = x;
        for (int i=1; i<n; i++) {
           answer[i] = answer[i-1] + x;
        }
        return answer;
    }
}

 

728x90
반응형

 

 

start 지점까지 가서 뭔가를 저장하고있다가 뒤집어야겠다는 생각을 했었는데,

그러면 시간이 너무오래걸릴것같았다.

 

책의 풀이를 참고해보니 일단 start 지점까지 가는것으로 시작하였다.

 

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
    
    if (head == null) return head;
    
    ListNode root = new ListNode(0);
    root.next = head;
    
    ListNode start = head;
    
    if (int i=0; i<left-1; i++ {
    	start=start.next;
    }
    
    }
}

 

우선 null 예외처리를 해주고

 

이리저리 손질보고나서 리턴을 예쁘게 하기위해 root 라는 새로운 ListNode 를 만들어주고 head 를 연결했다.

나중에 리턴할때는 root.next로 리턴할것이다.

 

앞으로 보낼 ListNode start 를 하나 만들고 left 파라미터 만큼 이동하기로했다.

주어진숫자는 자릿수이기때문에 index에 맞추려고 -1 해줌.

 

그리고 어떤식으로 살펴갈까 생각을 했는데

 

앞에 있는걸 뒤로 옮기자니 도루묵이 되어버렸고

start 지점을 기억하고 뒤에서 ++ 한 자릿수만큼 이동한뒤 끌어와야겠다고 생각했다.

 

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
    
    if (head == null) return head;
    
    ListNode root = new ListNode(0);
    root.next = head;
    
    ListNode start = root;
    
    for (int i=0; i<left-1; i++) {
    	start=start.next;
    }
    
    ListNode end = start.next;
    
    for (int i=0; i<right-left; i++) {
    	ListNode tmp = start.next; //start의 next 따로저장
        start.next = end.next; //start next.next를 next로 땡겨옴
        end.next = end.next.next; //end의 자릿수를 뒤로 이동 
        start.next.next = tmp; //다시 원래의 next를 저장
    }
    return root.next;
    
    }
}

 

end 를 만들어주고 loof를 돌렸다.

 

첫번째 loop

head = 1 2 3 4 5 6

start =  1 2 3 4 5 6

end = 2 3 4 5 6

ListNode tmp = start.next;
start.next = end.next;

 

tmp = 2 3 4 5 6

start = 1  + 3 4 5 6

start 의 next 가 end 의 next로 당겨졌다.

 

start 는 head 이므로, head 도 변하였다.

head = 1 3 4 5 6

end.next = end.next.next;
start.next.next = tmp;

 

 

end = 2 4 5 6 

 

end 의 next가 next.next로 당겨지고 이때 tmp 도 3이 빠진 2 4 5 6 으로 변하는 것으로..이해했다..

 

start.next.next = tmp 를 통해서 start = 1 3 2 4 5 6

 

두번째 loop

루프돌기전에

start = 1 3 2 4 5 6

end = 2 4 5 6

ListNode tmp = start.next;
start.next = end.next;

tmp = 3 2 4 5 6

 

start = 1 + 4 5 6

end.next = end.next.next;
start.next.next = tmp;

 

end = 2 5 6

이때tmp도 3 2 5 6

 

start = 1 4 3 2 5 6

 

..

이런식으로 바꿔나가면 된다!

728x90

+ Recent posts