Jerry's Blog

Recording what I learned everyday

View on GitHub


6 July 2019

Angular (22) -- Sending Login Request

by Jerry Zhang

LeetCode Day 1: P38. Count and Say

题目

有一个整数序列,前五个数是

  1. 1
  2. 11
  3. 21
  4. 1211
  5. 111221

1 is read off as “one 1” or 11. 11 is read off as “two 1s” or 21. 21 is read off as “one 2, then one 1” or 1211.

每个数都“读”上一个数,然后形成一个新的数。比如第二个数“11”是怎么来的呢?因为第一个数是一个1。那第三个数“21”又是怎么来的呢?因为第二 个数是“11”,也就是两个1,也就是“21”。

1 ≤ n ≤ 30,求第n个String

我的思路:

通过递归算法,应该能很容易的算出第n个string。但是我觉得那样的话,时间复杂度会比较高。所以能否通过找规律的办法,找到第n个string的 内在规律呢?先用递归实现一下吧…

我的算法:

用for循环从第二个数开始,如果当前的数字等于前一个数字,counter++。(counter初始值是1,因为前一个数至少已经出现了一次)。 如果当前的数字不等于前一个数字,那就结算。我们通过counter已经知道了前面有多少个连续的相同的数字,同时用i-1作为index可以拿到前面 连续的数字是几,把这两个数字append到结果的string中即可。

坑:

出现了数组越界问题。在跳出循环后,要进行最后一次结算。因为前面结算的条件是“不一样”,而跳出后其实也是“不一样”了,所以要最后结算一次。

时间复杂度:

假设string长度为m,有n个数,时间复杂度就是O(mn)

代码

public class E_38_CountAndSay {
    public static String countAndSay(int n) {
        if (n == 1) {
            return "1";
        }
        String previous = countAndSay(n - 1);
        char[] chars = previous.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();

        int counter = 1;
        int i;
        for (i = 1; i < chars.length; i++) {
            if (chars[i] == chars[i-1]) {
                counter++;
            } else {
                stringBuilder.append(counter);
                stringBuilder.append(chars[i-1]);
                counter = 1;
            }
        }
        stringBuilder.append(counter);
        stringBuilder.append(chars[i-1]);
        return stringBuilder.toString();
    }

    public static void main(String[] args) {
        String s = countAndSay(7);
        System.out.println("s = " + s);
    }
}

Optional Field in an interface

Only one field is different, so we add a question mark and set the field registerd as an optional field.

export interface AuthResponseData {
  kind: string;
  idToken: string;
  email: string;
  refreshToken: string;
  expiresIn: string;
  localId: string;
  registered?: boolean;
}

We defined this interface in the service class, but we want to use it later in a component. Therefore, we can use export key word and then in the component class, we can import this service to get this interface.

Same Observable

Most code for the observable is the same, so we can declare an Observable and subscribe only once.

onSubmit(f: NgForm) {
    if (!f.valid) {
      return;
    }
    const email = f.value.email;
    const password = f.value.password;

    let authObservable: Observable<AuthResponseData>;

    this.isLoading = true;
    if (this.isLoginMode) {
      authObservable = this.authService.login(email, password);
    } else {
      authObservable = this.authService.signup(email, password);
    }

    authObservable.subscribe(resData => {
      console.log(resData);
      this.isLoading = false;
    }, errorMessage => {
      console.log(errorMessage);
      this.error = errorMessage;
      this.isLoading = false;
    });

    f.reset();
  }

Handling Errors in a same method.

In both sign up and log in methods, we need to handle errors in a pipe method. To avoid repeated code, we define a new private method.

private handleError(errorRes: HttpErrorResponse) {
    let errorMessage = 'An unknown error occured!';
    if (!errorRes.error || !errorRes.error.error) {
      return throwError(errorMessage);
    }
    switch (errorRes.error.error.message) {
      case 'EMAIL_EXISTS':
        errorMessage = 'This email exists already';
        break;
      case 'EMAIL_NOT_FOUND':
        errorMessage = 'This email does not exist';
        break;
      case 'INVALID_PASSWORD':
        errorMessage = 'This password is not correct.';
        break;
    }
    return throwError(errorMessage);
  }

This method takes a HttpErrorResponse object as argument and return an error message string. So we substitute this into the pipe to make the code cleaner.

signup(email: string, password: string) {
    return this.http.post<AuthResponseData>(
      'https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=AIzaSyCQUonbyGcWNNCk-jS2WWkgpR3U0TtkIdA',
      {
        email: email,
        password: password,
        returnSecureToken: true
      }
    ).pipe(catchError(this.handleError));
  }
  
  
login(email: string, password: string) {
    return this.http.post<AuthResponseData>(
      'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=AIzaSyCQUonbyGcWNNCk-jS2WWkgpR3U0TtkIdA',
      {
        email: email,
        password: password,
        returnSecureToken: true
      }
    ).pipe(catchError(this.handleError));
  }

Now, in the pipe method, we only need to pass in this handleError method.

tags: Angular